Escribir un sistema operativo para Raspberry Pi en C

19

Ya encontré los tutoriales de Baking Pi , pero solo usan lenguaje ensamblador . Seguí las primeras lecciones, pero ya me pregunto cómo usar C en su lugar. Quiero decir, hay una razón por la que inventaron idiomas de nivel superior. Intenté simplemente compilar el código C en un .oarchivo object ( ), compilando

.section .init
.globl _start
_start:

bl main

loop$:
b loop$

a otro archivo de objeto y vincularlos juntos y así obtener kernel.img. Luego reemplacé el núcleo ya presente por el mío, pero no ejecuta el código C. El código C que escribí debería encender el LED OK y luego regresar (luego viene loop$: b loop$). Pero el LED OK parpadea aleatoriamente algunas veces y luego simplemente se apaga. Aquí está mi 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;
}

¿Cómo uso C para el desarrollo del sistema operativo en una Raspberry Pi?

Dudo que sea un error en el código (aunque solo soy un aficionado). Sé que configurar C puede ser complicado, pero no soy el primero en hacer esto. AFAIK, todos los sistemas operativos dominantes actualmente están escritos principalmente en C, por lo que debe haber un artículo que explique el proceso. También estaría muy contento con una lista de pasos, así que puedo buscar esos pasos en Google y tal vez hacer una pregunta un poco menos amplia.

Nota: el ensamblaje ARM equivalente del código C anterior funciona bien. Enciende el LED (después de un poco de parpadeo). Creo (espero) que eso indique que mi Raspberry Pi está bien.

11684
fuente
C fue diseñado para ser lenguaje ensamblador portátil para Unix. Linux está escrito en C, puede ahorrar bastante tiempo mirando cómo se hace.
Thorbjørn Ravn Andersen
1
@ ThorbjørnRavnAndersen Creo que no estoy preparado para leer la fuente de Linux. Linux es mucho más complejo de lo que quiero saber, lo que oscurece las piezas interesantes para mí.
11684
1
Um, 'conecta' algunos LED.
11684
1
Gracias, pero quiero hacer la mayoría de las cosas yo mismo. Es un proyecto de aprendizaje.
11684
1
Debo admitir que nunca antes había visto una pregunta sobre cómo escribir un sistema operativo. Y hay algunas respuestas interesantes. Es una locura ...
Piotr Kula

Respuestas:

14

Escribí un kernel muy simple hace años, y lo ejecuté en un 386. No he hecho programación básica en años, pero en términos generales debes escribir un código de ensamblador que:

  • deshabilitar interrupciones durante el proceso de arranque
  • si el Pi tiene un controlador de memoria, deberá configurarlo
  • configurar una marca de tiempo
  • configurar el controlador de interrupción
  • configurar una pila para que pueda ejecutar el código C

Configurar la pila es fácil: encuentre algo de memoria que no se esté utilizando y cargue esa dirección en el registro que se use como puntero de la pila.

En su código C, debe iniciar estructuras de datos del sistema operativo, como agrupaciones de memoria y tablas de hilos. No podrá utilizar las funciones de la biblioteca C: deberá escribir esas cosas usted mismo.

Si desea escribir un sistema operativo multitarea simple, deberá escribir algunas rutinas de ensamblador para guardar los registros de la CPU en la pila y cargar un conjunto diferente de valores de registro desde la pila de otro hilo. Y necesitará escribir una API para crear diferentes hilos.

Steve
fuente
1
Es difícil elegir entre esta respuesta y la de Georges Dupéron. Acepté este y le di un voto al otro.
11684
13

No he visto tu código en profundidad, pero me parece que estás en el camino correcto. Asegúrate de eso:

  • El _startsímbolo es el que se usa al compilar y vincular su archivo de ensamblaje y su archivo C (y eso main()no se usa en su lugar)
  • Al llamar main(), debe usar la convención de llamadas C:
    • presione en la pila la dirección de la instrucción que sigue a su llamada (la dirección de retorno, que será utilizada por la returndeclaración en C)
    • empujar los argumentos para la función. En su caso, puede insertar dos valores de 32 bits (8 bytes en total), pero para simplificar las cosas también podría eliminar los argumentos y simplemente tenerint main() { ... }
    • tal vez reserve algo de espacio en la pila para el valor de retorno
    • No puedo recordar en qué orden deberían empujarse estas cosas
    • Para saber qué espera exactamente la función C, desmóntela ( objdump -S main.o) y observe cómo manipula la pila.
  • Si no respeta la convención de llamada, entonces el código de ensamblaje generado por el compilador de C podría alterar la dirección de retorno en la pila, y en su caso ni siquiera presionó una dirección de retorno, por lo que la instrucción de retorno saltará a alguna parte aleatorio, en lugar de ir a loop$.

El wiki de OSDev será un recurso muy útil: se ocupa principalmente del desarrollo x86, pero la mayoría de la información sigue siendo aplicable a la frambuesa pi.

Algunos más recursos específicos de raspberry-pi osdev:

Suzanne Dupéron
fuente
Es difícil elegir entre esta respuesta y la de Steve. Te di un voto positivo y acepté el otro. Lamento la diferencia de 5 repeticiones.
11684
El wiki de OSDev es bueno, e incluso tiene algunas cosas específicas de RasPi
wally
2

El principal problema que puede encontrar son las bibliotecas C y el código de prólogo. Se inicia antes de que su propio código comience a ejecutarse y configura la pila, el montón y hace muchas otras cosas útiles. Sin embargo, cuando intentas programar para metal desnudo, no tienes ningún sistema operativo que se ejecute debajo de ti y es mejor evitar llamar a estas funciones. Para hacerlo, necesita versiones modificadas de las bibliotecas C y / o algunos símbolos globales definidos o reemplazados por los suyos. Este proceso es un poco complicado, por eso la gente de 'Baking Pi' eligió usar el ensamblaje para sus tutoriales.

lenik
fuente
Gracias por responder mi pregunta (y perdón por responder tan tarde). Pero (¡sorpresa!) Compré mi pi para aprender sobre eso, la parte que involucra procesos de bajo nivel (prefiero no hacerlo en un escritorio costoso con el riesgo de destruir archivos / correos / fotos personales). ¿Podría agregar cómo configuro la pila, o un artículo / tutorial / algún recurso que lo explique? (Y qué más podría necesitar para ejecutar C).
11684
2

Intenta esto en su lugar:

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

Además, la experiencia x86 es un poco diferente. Puede ser aplicable a la programación general del sistema operativo ARM bare metal. Pero para Pi, lo siento, es el inicio de gpu primero y se configura bastante antes del código de su sistema operativo (?).

Dennis Ng
fuente
1
Un poco más de detalle sería genial, ¿qué sucede si se rompe el enlace en su respuesta?
Darth Vader
Todavía está allí, pero creo que para aquellos que vienen aquí, que googleen "válvulas de metal desnudo" y mejor prueben la serie OSDEV (para superar el cross dev one mientras luchaba, lean el foro; publico uno, pueden probar google "OSDEV foro seis meses cruzado ")
Dennis Ng
Sé que esta es una vieja respuesta a una pregunta aún más antigua, pero la página está en web.archive.org en caso de que caiga.
anonymoose
1

s-matyukevich/raspberry-pi-os

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

Este impresionante repositorio hace tanto el arranque en C y trata temas bastante complejos.

Además, analiza cómo hace las cosas el kernel de Linux y anota el código del kernel de Linux.

Eche un vistazo al primer tutorial para una configuración minimalista: https://github.com/s-matyukevich/raspberry-pi-os/tree/43f682d406c8fc08736ca3edd08a1c8e477c72b0/src/lesson01/src

Lo recomiendo altamente.

Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
fuente