Napisz system operacyjny dla Raspberry Pi w C

19

Znalazłem już samouczki Baking Pi , ale używają one tylko języka asemblera . Poszłam na pierwsze lekcje, ale już zastanawiam się, jak zamiast tego użyć C. Mam na myśli powód, dla którego wymyślili języki wyższego poziomu. Próbowałem po prostu skompilować kod C do pliku object ( .o), kompilując

.section .init
.globl _start
_start:

bl main

loop$:
b loop$

do innego pliku obiektowego i łączenie ich ze sobą, a więc uzyskiwanie kernel.img. Następnie zastąpiłem już obecne jądro moim własnym, ale nie wykonuje ono kodu C. Kod C, który napisałem, powinien po prostu włączyć diodę OK, a następnie powrócić (potem nadejdzie loop$: b loop$). Ale dioda OK OK miga kilka razy losowo, a następnie pozostaje wyłączona. Oto mój kod C:

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

Jak używać C do programowania systemów operacyjnych na Raspberry Pi?

Wątpię, czy to błąd w kodzie (chociaż jestem tylko hobbystą). Wiem, że konfiguracja C może być skomplikowana, ale nie jestem pierwszą, która to robi. AFAIK, wszystkie obecnie dominujące systemy operacyjne są napisane głównie w C, więc musi być artykuł wyjaśniający ten proces. Byłbym też bardzo zadowolony z listy kroków, więc mogę wyszukiwać te kroki w Google i być może zadać pytanie nieco mniej ogólne.

Uwaga: odpowiednik zestawu ARM powyższego kodu C działa dobrze. Włącza diodę LED (po krótkim mrugnięciu). Myślę (mam nadzieję), że to wskazuje, że moje Raspberry Pi jest w porządku.

11684
źródło
C został zaprojektowany jako przenośny język asemblera dla Uniksa. Linux jest napisany w C, możesz zaoszczędzić sporo czasu, patrząc na to, jak się to robi.
Thorbjørn Ravn Andersen
1
@ ThorbjørnRavnAndersen Myślę, że nie mam zamiaru czytać źródła Linuksa. Linux jest o wiele bardziej złożony niż to, co chcę wiedzieć, przez co zaciemnia dla mnie interesujące elementy.
11684,
1
Um, „podłącz” kilka diod LED.
11684
1
Dziękuję, ale chcę robić większość rzeczy sam. To projekt edukacyjny.
11684,
1
Muszę przyznać, że nigdy wcześniej nie widziałem pytania, jak napisać system operacyjny. I jest kilka interesujących odpowiedzi. To po prostu szalone ...
Piotr Kula,

Odpowiedzi:

14

Wiele lat temu napisałem bardzo proste jądro i uruchomiłem je na 386. Od wielu lat nie programowałem bez systemu, ale ogólnie rzecz biorąc, musisz napisać kod asemblera, który:

  • wyłącz przerwania podczas procesu uruchamiania
  • jeśli Pi ma kontroler pamięci, musisz go skonfigurować
  • ustawić znacznik czasu
  • skonfiguruj kontroler przerwań
  • ustaw stos, abyś mógł wykonać kod C.

Konfigurowanie stosu jest łatwe - znajdź pamięć, która nie jest używana, i załaduj adres, pod którym kiedykolwiek rejestr jest używany jako wskaźnik stosu.

W kodzie C musisz zainicjować struktury danych systemu operacyjnego, takie jak pule pamięci i tabele wątków. Nie będziesz mógł korzystać z funkcji biblioteki C - musisz sam to napisać.

Jeśli chcesz napisać prosty wielozadaniowy system operacyjny, musisz napisać kilka procedur asemblera, aby zapisać rejestry procesora na stosie i załadować inny zestaw wartości rejestru ze stosu innego wątku. I musisz napisać API, aby utworzyć różne wątki.

Steve
źródło
1
Trudno wybrać między tą odpowiedzią a odpowiedzią Georgesa Dupérona. Zaakceptowałem ten i oddałem głos drugiemu.
11684
13

Nie zagłębiłem się w twój kod, ale wydaje mi się, że jesteś na dobrej drodze. Upewnij się, że:

  • Ten _startsymbol jest rzeczywiście tym, który jest używany podczas kompilacji i łączenia pliku asemblera i pliku C (i main()nie jest on używany zamiast tego)
  • Podczas dzwonienia main()należy użyć konwencji wywoływania C:
    • wcisnij na stos adres instrukcji po twoim wywołaniu (adres zwrotny, który będzie używany przez returninstrukcję w C)
    • wypchnij argumenty dla funkcji. W twoim przypadku możesz wcisnąć dwie wartości 32-bitowe (łącznie 8 bajtów), ale dla uproszczenia możesz również usunąć argumenty i po prostu miećint main() { ... }
    • może zarezerwować trochę miejsca na stosie na wartość zwracaną
    • Nie pamiętam, w jakiej kolejności te rzeczy powinny być popychane
    • Aby wiedzieć, czego dokładnie oczekuje funkcja C, zdemontuj ją ( objdump -S main.o) i zobacz, jak manipuluje stosem.
  • Jeśli nie przestrzegasz konwencji wywoływania, kod asemblera wygenerowany przez kompilator C może manipulować adresem zwrotnym na stosie, aw twoim przypadku nawet nie pchnąłeś adresu zwrotnego, więc instrukcja powrotu gdzieś przeskoczy losowe, zamiast iść do loop$.

OSDev wiki będzie bardzo przydatna Ressource - to dotyczyły głównie z rozwojem x86 ale większość informacji jest nadal stosowane do pi malinowym.

Kilka innych zasobów specyficznych dla raspberry-pi osdev:

Suzanne Dupéron
źródło
Trudno wybrać między tą odpowiedzią a odpowiedzią Steve'a. Dałem ci głos i zaakceptowałem drugą. Żałuję różnicy 5 powtórzeń.
11684
OSDev wiki jest dobre - a nawet ma pewne specyficzne raspi rzeczy
Wally
2

Głównym problemem, jaki możesz napotkać, są biblioteki C i kod prologu. Uruchamia się, zanim twój własny kod zacznie działać i ustawi stos, stos i zrobi wiele innych pomocnych rzeczy. Jednak, gdy próbujesz programować na goły metal, nie masz systemu operacyjnego działającego pod tobą i lepiej unikać wywoływania tych funkcji. W tym celu potrzebujesz zmodyfikowanych wersji bibliotek C i / lub niektórych symboli globalnych zdefiniowanych lub zastąpionych własnymi. Ten proces jest nieco angażujący, dlatego ludzie „Baking Pi” zdecydowali się użyć asemblera do swoich samouczków.

Lenik
źródło
Dziękuję za odpowiedź na moje pytanie (i przepraszam za odpowiedź tak późno). Ale (niespodzianka!) Kupiłem swoje pi, aby dowiedzieć się o tym, nieco w procesach niskiego poziomu (wolałbym nie robić tego na drogim komputerze z ryzykiem zniszczenia osobistych plików / maili / zdjęć). Czy mógłbyś dodać, jak skonfigurowałem stos, lub artykuł / samouczek / jakiś zasób, który to wyjaśnia? (I czego jeszcze może potrzebować do uruchomienia C).
11684
2

Spróbuj zamiast tego:

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

Ponadto wrażenia z x86 są nieco inne. Może mieć zastosowanie do ogólnego programowania systemu operacyjnego ARM bez systemu operacyjnego. Ale dla Pi, przepraszam, że najpierw zaczyna się procesor GPU i ustawia się sporo przed kodem OS (?).

Dennis Ng
źródło
1
Byłoby trochę więcej szczegółów, co się stanie, jeśli link w twojej odpowiedzi się zepsuje?
Darth Vader
Nadal tam jest, ale myślę, że dla tych, którzy tu przychodzą, mogą google „zawory goły metal” i lepiej wypróbować serię OSDEV (aby przejść obok cross dev dev, gdy walczyłem, przeczytaj forum; zamieszczam jedną, możesz wypróbować google „OSDEV” forum sześć miesięcy krzyż ”)
Dennis Ng
Wiem, że to stara odpowiedź na jeszcze starsze pytanie, ale strona znajduje się na web.archive.org na wypadek, gdyby się zawaliła .
anonimowy