Scrivi un sistema operativo per Raspberry Pi in C


19

Ho già trovato i tutorial di Baking Pi , ma usano solo il linguaggio assembly . Ho seguito le prime lezioni, ma mi sto già chiedendo come usare invece C. Voglio dire, c'è una ragione per cui hanno inventato lingue di livello superiore. Ho provato a compilare il codice C in un .ofile object ( ), compilando

.section .init
.globl _start
_start:

bl main

loop$:
b loop$

a un altro file oggetto e collegandoli insieme e ottenendo così kernel.img. Ho quindi sostituito il kernel già presente con il mio, ma non esegue il codice C. Il codice C che ho scritto dovrebbe semplicemente accendere il LED OK e quindi tornare (quindi arriva loop$: b loop$). Ma il LED OK lampeggia in modo casuale alcune volte e poi rimane spento. Ecco il mio codice C:

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

Come posso usare C per lo sviluppo del sistema operativo su un Raspberry Pi?

Dubito che sia un errore nel codice (anche se sono solo un hobbista). Sono consapevole che la configurazione di C potrebbe essere complicata, ma non sono il primo a farlo. AFAIK, tutti i sistemi operativi attualmente dominanti sono scritti principalmente in C, quindi deve esserci un articolo che spieghi il processo. Sarei molto contento anche di un elenco di passaggi, quindi posso google per quei passaggi e forse porre una domanda un po 'meno ampia.

Nota: l'equivalente dell'assieme ARM del codice C sopra funziona perfettamente. Accende il LED (dopo un po 'di lampeggiamento). Penso (spero) che indichi che il mio Raspberry Pi sta bene.


C è stato progettato per essere un linguaggio assembly portatile per Unix. Linux è scritto in C, puoi risparmiare un bel po 'di tempo osservando come è fatto.
Thorbjørn Ravn Andersen,

1
@ ThorbjørnRavnAndersen Penso che non sono in grado di leggere la fonte di Linux. Linux è molto più complesso di quello che voglio sapere, oscurando così per me pezzi interessanti.
11684,

1
Uhm, "collega" alcuni LED.
11684,

1
Grazie, ma voglio fare la maggior parte delle cose da solo. È un progetto di apprendimento.
11684,

1
Devo ammettere di non aver mai visto prima una domanda su come scrivere un sistema operativo. E ci sono alcune risposte interessanti. È semplicemente pazzesco ...
Piotr Kula,

Risposte:


14

Ho scritto un kernel molto semplice anni fa e l'ho eseguito su un 386. Non ho programmato bare metal in questi anni, ma in termini generali è necessario scrivere un codice assembler che:

  • disabilita gli interrupt durante il processo di avvio
  • se il Pi ha un controller di memoria, dovrai configurarlo
  • impostare un segno di spunta del timer
  • configurare il controller di interrupt
  • impostare uno stack in modo da poter eseguire il codice C.

Configurare lo stack è semplice: trova un po 'di memoria che non viene utilizzata e carica l'indirizzo in cui viene mai registrato il registro come puntatore dello stack.

Nel codice C è necessario avviare strutture di dati del sistema operativo come pool di memoria e tabelle thread. Non sarai in grado di utilizzare le funzioni della libreria C: dovrai scrivere tu stesso quel materiale.

Se si desidera scrivere un semplice sistema operativo multitasking, è necessario scrivere alcune routine di assemblaggio per salvare i registri della CPU nello stack e caricare un diverso set di valori di registro dallo stack di un altro thread. E dovrai scrivere un'API per creare thread diversi.


1
Difficile scegliere tra questa risposta e quella di Georges Dupéron. Ho accettato questo e ho dato un altro voto.
11684,

13

Non ho approfondito il tuo codice, ma mi sembra che tu sia sulla buona strada. Assicurati che:

  • Il _startsimbolo è in effetti quello usato durante la compilazione e il collegamento del file di assieme e del file C (e che main()invece non viene utilizzato)
  • Quando si chiama main(), è necessario utilizzare la convenzione di chiamata C:
    • spingere sullo stack l'indirizzo dell'istruzione dopo la chiamata (l'indirizzo di ritorno, che verrà utilizzato dall'istruzione returnin C)
    • spingere gli argomenti per la funzione. Nel tuo caso puoi spingere due valori a 32 bit (8 byte in totale), ma per semplificare le cose potresti anche rimuovere gli argomenti e semplicementeint main() { ... }
    • forse riservare un po 'di spazio sullo stack per il valore restituito
    • Non ricordo in che ordine queste cose dovrebbero essere spinte
    • Per sapere cosa si aspetta esattamente la funzione C, smontala ( objdump -S main.o) e osserva come manipola lo stack.
  • Se non rispetti la convenzione di chiamata, il codice assembly generato dal compilatore C potrebbe manomettere l'indirizzo di ritorno nello stack e nel tuo caso non hai nemmeno inserito un indirizzo di ritorno, quindi l'istruzione di ritorno salterà da qualche parte casuale, invece di andare loop$.

La wiki di OSDev sarà una risorsa molto utile - riguarda principalmente lo sviluppo di x86 ma la maggior parte delle informazioni è ancora applicabile al raspberry pi.

Altre risorse specifiche per osdev raspberry-pi:


Difficile scegliere tra questa risposta e quella di Steve. Ti ho dato un voto e ho accettato l'altro. Mi dispiace per la differenza di 5 ripetizioni.
11684,

Il wiki di OSDev è buono - e ha anche alcune cose specifiche su RasPi
wally il

2

Il problema principale che potresti incontrare sono le librerie C e il codice del prologo. È iniziato prima che il tuo codice inizi a essere eseguito e imposta lo stack, l'heap e fa molte altre cose utili. Tuttavia, quando stai provando a programmare per bare metal non hai nessun sistema operativo in esecuzione sotto di te e faresti meglio a evitare di chiamare queste funzioni. Per fare ciò sono necessarie versioni modificate delle librerie C e / o alcuni simboli globali definiti o sostituiti con i propri. Questo processo è un po 'coinvolgente, ecco perché le persone di "Baking Pi" hanno scelto di usare l'assemblaggio per i loro tutorial.


Grazie per aver risposto alla mia domanda (e scusate per aver risposto così tardi). Ma (sorpresa!) Ho comprato il mio pi per saperne di più, il bit che coinvolge processi di basso livello (preferirei non farlo su un desktop costoso con il rischio di distruggere file / mail / foto personali). Potresti aggiungere come ho impostato lo stack o un articolo / tutorial / alcune risorse che lo spiegano? (E cos'altro potrei aver bisogno di eseguire C).
11684

2

Prova questo invece:

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

Inoltre, l'esperienza x86 è leggermente diversa. Può essere applicabile alla programmazione generale del sistema operativo bare metal ARM. Ma per Pi, mi dispiace che sia la gpu a iniziare prima e configurata un po 'prima del codice del tuo sistema operativo (?).


1
Un dettaglio in più sarebbe fantastico, cosa succede se il link nella tua risposta si interrompe?
Darth Vader

È ancora lì, ma penso che per quelli che vengono qui, possono google "valvole bare metal" e meglio provare la serie OSDEV (per superare la croce dev mentre ne ho faticato, leggi il forum; ne inserisco una puoi provare google "OSDEV croce di sei mesi del forum ")
Dennis Ng,

So che questa è una vecchia risposta a una domanda ancora più vecchia, ma la pagina si trova su web.archive.org nel caso in cui dovesse cadere.
anonymoose,

1

s-matyukevich/raspberry-pi-os

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

Questo fantastico repository esegue sia il bootstraping in C, sia argomenti piuttosto complessi.

Inoltre, esamina come il kernel Linux fa le cose e annota il codice del kernel Linux.

Dai un'occhiata al primo tutorial per un'installazione minimalista: https://github.com/s-matyukevich/raspberry-pi-os/tree/43f682d406c8fc08736ca3edd08a1c8e477c72b0/src/lesson01/src

Lo consiglio vivamente.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.