Écrire un OS pour Raspberry Pi en C


19

J'ai déjà trouvé les tutoriels Baking Pi , mais ils utilisent uniquement le langage d'assemblage . J'ai suivi les premières leçons, mais je me demande déjà comment utiliser C à la place. Je veux dire, il y a une raison pour laquelle ils ont inventé des langages de niveau supérieur. J'ai essayé de compiler le code C dans un .ofichier object ( ), en compilant

.section .init
.globl _start
_start:

bl main

loop$:
b loop$

à un autre fichier objet et les reliant entre eux et ainsi obtenir kernel.img. J'ai ensuite remplacé le noyau déjà présent par le mien, mais il n'exécute pas le code C. Le code C que j'ai écrit devrait simplement allumer la LED OK puis revenir (puis vient loop$: b loop$). Mais la LED OK clignote plusieurs fois au hasard, puis reste éteinte. Voici mon code C:

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

Comment utiliser C pour le développement de systèmes d'exploitation sur un Raspberry Pi?

Je doute que ce soit une erreur dans le code (même si je ne suis qu'un amateur). Je suis conscient que la configuration de C peut être compliquée, mais je ne suis pas le premier à le faire. AFAIK, tous les OS actuellement dominants sont principalement écrits en C, il doit donc y avoir un article expliquant le processus. Je serais également très heureux d'avoir une liste d'étapes, je peux donc rechercher ces étapes sur Google et peut-être poser une question un peu moins large.

Remarque: l'équivalent d'assemblage ARM du code C ci-dessus fonctionne très bien. Il allume la LED (après un peu de clignotement). Je pense (j'espère) que cela indique que mon Raspberry Pi va bien.


C a été conçu pour être un langage d'assemblage portable pour Unix. Linux est écrit en C, vous pouvez gagner un peu de temps en regardant comment cela se fait.
Thorbjørn Ravn Andersen

1
@ ThorbjørnRavnAndersen Je pense que je ne suis pas à la hauteur de la source de Linux. Linux est beaucoup plus complexe que ce que je veux savoir, obscurcissant ainsi les morceaux intéressants pour moi.
11684

1
Hum, connectez quelques LED.
11684

1
Merci, mais je veux faire la plupart des choses moi-même. C'est un projet d'apprentissage.
11684

1
Je dois admettre que je n'ai jamais vu de question auparavant sur la façon d'écrire un système d'exploitation. Et il y a des réponses intéressantes. C'est juste fou ...
Piotr Kula

Réponses:


14

J'ai écrit un noyau très simple il y a des années et je l'ai exécuté sur un 386. Je n'ai pas fait de programmation bare metal depuis des années, mais en termes généraux, vous devez écrire du code assembleur qui:

  • désactiver les interruptions pendant le processus de démarrage
  • si le Pi a un contrôleur de mémoire, vous devrez le configurer
  • configurer une minuterie
  • configurer le contrôleur d'interruption
  • configurer une pile pour pouvoir exécuter du code C

La configuration de la pile est facile - trouvez de la mémoire qui n'est pas utilisée et chargez cette adresse dans laquelle le registre est utilisé comme pointeur de pile.

Dans votre code C, vous devez initialiser les structures de données du système d'exploitation comme les pools de mémoire et les tables de threads. Vous ne pourrez pas utiliser les fonctions de la bibliothèque C - vous devrez écrire ce truc vous-même.

Si vous souhaitez écrire un système d'exploitation multitâche simple, vous devrez écrire des routines d'assembleur pour enregistrer les registres du processeur sur la pile et charger un ensemble différent de valeurs de registre à partir de la pile d'un autre thread. Et vous devrez écrire une API pour créer différents threads.


1
Difficile de choisir entre cette réponse et celle de Georges Dupéron. J'ai accepté celui-ci et ai donné à l'autre un vote positif.
11684

13

Je n'ai pas examiné votre code en profondeur, mais il me semble que vous êtes sur la bonne voie. Sois sûr que:

  • Le _startsymbole est en effet celui utilisé lors de la compilation et de la liaison de votre fichier d'assemblage et de votre fichier C (et qui main()n'est pas utilisé à la place)
  • Lors de l'appel main(), vous devez utiliser la convention d'appel C:
    • poussez sur la pile l'adresse de l'instruction suivant votre appel (l'adresse de retour, qui sera utilisée par l' returninstruction en C)
    • pousser les arguments de la fonction. Dans votre cas, vous pouvez pousser deux valeurs 32 bits (8 octets au total), mais pour simplifier les choses, vous pouvez également supprimer les arguments et simplement avoirint main() { ... }
    • peut-être réserver de l'espace sur la pile pour la valeur de retour
    • Je ne me souviens pas dans quel ordre ces choses doivent être poussées
    • Pour savoir exactement ce que la fonction C attend, démontez-la ( objdump -S main.o) et regardez comment elle manipule la pile.
  • Si vous ne respectez pas la convention d'appel, le code assembleur généré par le compilateur C peut altérer l'adresse de retour sur la pile, et dans votre cas, vous n'avez même pas poussé d'adresse de retour, donc l'instruction de retour sautera quelque part aléatoire, au lieu d'aller loop$.

Le wiki OSDev sera une ressource très utile - il concerne principalement le développement x86 mais la plupart des informations sont toujours applicables au raspberry pi.

Quelques ressources spécifiques à Raspberry-Pi OSDEV:


Difficile de choisir entre cette réponse et celle de Steve. Je vous ai donné un vote positif et j'ai accepté l'autre. Je regrette la différence de 5 répétitions.
11684

Le wiki OSDev est bon - et a même des trucs RasPi spécifiques
wally

2

Le principal problème que vous pourriez rencontrer est les bibliothèques C et le code de prologue. Cela a commencé avant que votre propre code commence à s'exécuter et configure la pile, le tas et fait beaucoup d'autres choses utiles. Cependant, lorsque vous essayez de programmer pour du métal nu, vous n'avez aucun système d'exploitation en dessous de vous et vous feriez mieux d'éviter d'appeler ces fonctions. Pour ce faire, vous avez besoin de versions modifiées des bibliothèques C et / ou de certains symboles globaux définis ou remplacés par les vôtres. Ce processus est un peu compliqué, c'est pourquoi les gens de 'Baking Pi' ont choisi d'utiliser l'assemblage pour leurs tutoriels.


Merci d'avoir répondu à ma question (et désolé d'avoir répondu si tard). Mais (surprise!) J'ai acheté mon pi pour en savoir plus, le peu impliquant des processus de bas niveau (je préfère ne pas le faire sur un bureau cher avec le risque de détruire des fichiers / mails / photos personnels). Pourriez-vous s'il vous plaît ajouter comment j'ai configuré la pile, ou un article / tutoriel / une ressource expliquant cela? (Et de quoi d'autre pourrais-je avoir besoin pour exécuter C).
11684

2

Essayez plutôt ceci:

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

De plus, l'expérience x86 est un peu différente. Il peut s'appliquer à la programmation générale du système d'exploitation ARM bare metal. Mais pour Pi, désolé c'est le démarrage du GPU en premier et mis en place un peu avant votre code OS (?).


1
Un peu plus de détails serait génial, que se passe-t-il si le lien dans votre réponse se casse?
Dark Vador

Il est toujours là mais je pense que pour ceux qui viennent ici, peut google "valves bare metal" et mieux essayer la série OSDEV (pour passer le cross dev one pendant que je me débattais, lisez le forum; j'en poste un, vous pouvez essayer google "OSDEV forum six mois cross ")
Dennis Ng

Je sais que c'est une vieille réponse à une question encore plus ancienne, mais la page est sur web.archive.org au cas où elle tomberait.
anonymoose

1

s-matyukevich/raspberry-pi-os

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

Ce repo génial fait à la fois le bootstraping C et aborde des sujets assez complexes.

De plus, il examine comment le noyau Linux fait les choses et annote le code du noyau Linux.

Jetez un œil au premier tutoriel pour une configuration minimaliste: https://github.com/s-matyukevich/raspberry-pi-os/tree/43f682d406c8fc08736ca3edd08a1c8e477c72b0/src/lesson01/src

Je le recommande fortement.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.