Escreva um SO para Raspberry Pi em C

19

Eu já encontrei os tutoriais do Baking Pi , mas eles usam apenas a linguagem assembly . Eu segui as primeiras lições, mas já estou imaginando como usar o C. Quero dizer, há uma razão pela qual eles inventaram linguagens de nível superior. Eu tentei apenas compilar o código C em um .oarquivo object ( ), compilando

.section .init
.globl _start
_start:

bl main

loop$:
b loop$

para outro arquivo de objeto e vinculá-los e, assim, obter kernel.img. Substituí o kernel já presente pelo meu, mas ele não executa o código C. O código C que escrevi deve acender o LED OK e retornar (depois vem loop$: b loop$). Mas o LED OK pisca aleatoriamente algumas vezes e fica desligado. Aqui está o meu código C:

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

Como uso o C para o desenvolvimento de sistemas operacionais em um Raspberry Pi?

Duvido que seja um erro no código (embora eu seja apenas um hobby). Estou ciente de que configurar C pode ser complicado, mas não sou o primeiro a fazer isso. AFAIK, todos os sistemas operacionais dominantes atualmente são escritos principalmente em C, portanto, deve haver um artigo explicando o processo. Eu ficaria muito feliz com uma lista de etapas também, para poder pesquisar essas etapas no Google e talvez fazer uma pergunta um pouco menos ampla.

Nota: o conjunto ARM equivalente do código C acima funciona perfeitamente. Acende o LED (depois de piscar um pouco). Eu acho que (espero) que indica que meu Raspberry Pi está bem.

11684
fonte
C foi projetado para ser uma linguagem de montagem portátil para Unix. O Linux é escrito em C, você pode economizar bastante tempo observando como isso é feito.
Thorbjørn Ravn Andersen
11
@ ThorbjørnRavnAndersen Acho que não estou conseguindo ler a fonte do Linux. O Linux é muito mais complexo do que o que eu quero saber, obscurecendo as peças interessantes para mim.
11684
11
Hum, conecte alguns LEDs.
11684
11
Obrigado, mas eu quero fazer a maioria das coisas sozinho. É um projeto de aprendizado.
11684
11
Devo admitir que nunca vi uma pergunta em nenhum lugar sobre como escrever um sistema operacional. E há algumas respostas interessantes. É simplesmente uma loucura ...
Piotr Kula

Respostas:

14

Escrevi um kernel muito simples anos atrás e o executei em um 386. Não faço programação bare metal há anos, mas em termos gerais, você precisa escrever algum código de assembler que:

  • desativar interrupções durante o processo de inicialização
  • se o Pi tiver um controlador de memória, você precisará configurá-lo
  • configurar uma marca de timer
  • configurar o controlador de interrupção
  • configurar uma pilha para que você possa executar o código C

É fácil configurar a pilha - encontre alguma memória que não esteja sendo usada e carregue o endereço no qual cada registro é usado como ponteiro da pilha.

No seu código C, você precisa iniciar estruturas de dados do SO, como conjuntos de memórias e tabelas de encadeamentos. Você não poderá usar as funções da biblioteca C - precisará escrever essas coisas sozinho.

Se você deseja escrever um sistema operacional multitarefa simples, precisará escrever algumas rotinas de assembler para salvar os registros da CPU na pilha e carregar um conjunto diferente de valores de registro da pilha de outra thread. E você precisará escrever uma API para criar diferentes threads.

Steve
fonte
11
Difícil escolher entre essa resposta e a de Georges Dupéron's. Eu aceitei este e dei ao outro um voto positivo.
11684 17/09/2013
13

Não analisei seu código detalhadamente, mas parece-me que você está no caminho certo. Certifique-se de que:

  • O _startsímbolo é realmente o usado ao compilar e vincular seu arquivo de montagem e seu arquivo C (que main()não é usado)
  • Ao ligar main(), você precisa usar a convenção de chamada C:
    • pressione na pilha o endereço da instrução após a sua chamada (o endereço de retorno, que será usado pela returninstrução em C)
    • envie os argumentos para a função. No seu caso, você pode enviar dois valores de 32 bits (8 bytes no total), mas para simplificar, você também pode remover os argumentos e apenas terint main() { ... }
    • talvez reserve algum espaço na pilha para o valor de retorno
    • Não me lembro em que ordem essas coisas devem ser empurradas
    • Para saber exatamente o que a função C espera, desmonte-a ( objdump -S main.o) e veja como ela manipula a pilha.
  • Se você não respeitar a convenção de chamada, o código do assembly gerado pelo compilador C poderá violar o endereço de retorno na pilha e, no seu caso, você nem mesmo inseriu um endereço de retorno, para que a instrução de retorno salte para algum lugar aleatória, em vez de ir para loop$ .

O wiki do OSDev será um muito útil - ele se preocupa principalmente com o desenvolvimento do x86, mas a maioria das informações ainda é aplicável ao raspberry pi.

Mais alguns recursos específicos do raspberry-pi osdev:

Suzanne Dupéron
fonte
Difícil escolher entre essa resposta e a de Steve. Eu te dei um voto positivo e aceitei o outro. Lamento a diferença de 5 repetições.
11684 17/09/2013
OSDev wiki é bom - e ainda tem alguns específicos Raspi coisas
wally
2

O principal problema que você pode encontrar são as bibliotecas C e o código de prólogo. É iniciado antes que seu próprio código comece a ser executado e configure a pilha, a pilha e faça muitas outras coisas úteis. No entanto, quando você está tentando programar o bare metal, não possui nenhum SO rodando abaixo de você e é melhor evitar chamar essas funções. Para fazer isso, você precisa de versões modificadas das bibliotecas C e / ou de alguns símbolos globais definidos ou substituídos pelos seus. Esse processo é um pouco envolvente, é por isso que o pessoal do 'Baking Pi' optou por usar a montagem em seus tutoriais.

lenik
fonte
Obrigado por responder à minha pergunta (e desculpe-me por responder tão tarde). Mas (surpresa!) Comprei meu pi para aprender exatamente isso, o que envolve processos de baixo nível (prefiro não fazer isso em uma área de trabalho cara com o risco de destruir arquivos pessoais / e-mails / fotos). Você poderia adicionar como eu montei a pilha, ou um artigo / tutorial / algum recurso explicando isso? (E o que mais eu preciso executar C).
11684
2

Tente isso:

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

Além disso, a experiência x86 é um pouco diferente. Pode ser aplicável à programação geral do SO bare metal do ARM. Mas para o Pi, desculpe, é o gpu iniciar primeiro e configurar um pouco antes do código do sistema operacional (?).

Dennis Ng
fonte
11
Um pouco mais de detalhes seria ótimo. O que acontece se o link em sua resposta quebrar?
Darth Vader
Ainda está lá, mas acho que para quem vem até aqui, pode pesquisar no google "válvulas bare metal" e melhor tentar a série OSDEV (para ultrapassar o cross dev um enquanto eu lutei, leia o fórum; eu posto um que você pode tentar no google "OSDEV forum six month cross ")
Dennis Ng
Eu sei que essa é uma resposta antiga para uma pergunta ainda mais antiga, mas a página está em web.archive.org , caso caia.
anonymoose
1

s-matyukevich/raspberry-pi-os

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

Este repo impressionante faz o bootstrap C e entra em tópicos bastante complexos.

Além disso, analisa como o kernel do Linux faz as coisas e anota o código do kernel do Linux.

Dê uma olhada no primeiro tutorial para uma configuração minimalista: https://github.com/s-matyukevich/raspberry-pi-os/tree/43f682d406c8fc08736ca3edd08a1c8e477c72b0/src/lesson01/src

Eu recomendo.

Ciro Santilli adicionou uma nova foto
fonte