He escrito un ejemplo de núcleo múltiple de metal desnudo.
Código, el diagrama del circuito está aquí: https://github.com/jeffreyantony/multipi/tree/master/Example_01
En mi ejemplo, hay 3 LED conectados a los pines GPIO de la frambuesa Pi. Hay totalmente 4 núcleos en Raspberry Pi 2. Cada núcleo está asignado para parpadear su LED correspondiente.
Escribí la dirección del código que debe ejecutar cada núcleo en las siguientes direcciones 0x4000009C para el núcleo 1 0x400000AC para el núcleo 2 0x400000BC para el núcleo 3
Después de compilar el código, solo el LED asignado al núcleo 1 parpadea (como en este ejemplo, LED amarillo). Otros no lo son.
Esto significa que el código para Core 2 y 3 no se está ejecutando (ya que los otros LED no parpadean). También descubrí que el código después de iniciar todos los núcleos tampoco se está ejecutando, es decir, core0_submain (): esta función debería parpadear el LED ACT en la Raspberry Pi
¿Alguien podría decirme cuál es el problema? ¿Es porque los 4 núcleos intentan escribir en el mismo registro GPIO y solo Core 1 gana en la escritura?
Traté de agregar " atributo ((desnudo));" para core0_submain () pero no sirvió de nada.
Estoy usando la cadena de herramientas de https://launchpad.net/gcc-arm-embedded
una vez más código - https://github.com/jeffreyantony/multipi/blob/master/Example_01/main.c
makefile - https://github.com/jeffreyantony/multipi/blob/master/Example_01/Makefile
Actualización 20 de octubre de 2015 : he agregado soporte para JTAG. Pero no se pudo obtener la interfaz de depuración
Actualización 25 de octubre de 2015 : se solucionó el problema. Ver respuesta.
fuente
Respuestas:
Actualización 25 oct 2015:
El foro Raspberry Pi me dio la respuesta .
No existe el concepto de _start cuando se usa -nostdlib
el código que se ejecutará primero debe ser el primer archivo que se pase al vinculador.
Si se necesita un mejor control, el código debe colocarse en una sección de inicio y pedirle al vinculador que copie esta sección en
0x8000
Gracias a todos por el apoyo. Aprendí mucho sobre el compilador C de GNU.
Actualización 24 oct 2015:
Cuando cambié el orden de los archivos dados para compilar en el Makefile, obtuve el orden correcto (es decir
0x8000
, tenemos la_start
función) con-O2
optimización. Pero aún_start
no se resuelve mi pregunta de stackoverflow a continuación sobre el símbolo. Se ha registrado un nuevo código.He tenido algo de exito. El nuevo código se registra en github .
El ejemplo no se está ejecutando completamente. Hay algunos problemas con la compilación. Explicaré cada uno:
_start
tomara el símbolo de mi inicio personalizado. Pero no fue el caso. Debido a esto, el puntero de la pila no se configuró y el salto a main no ocurrió.Ya he hecho una pregunta sobre esto. Pero no he progresado mucho. Así que agregué un ensamblaje en línea para cargar el puntero de la pila en la función principal.
0x8000
(donde comienza la ejecución) de Raspberry Pi está el código para Core 1 -void core1_main(void)
. Mi suposición fue que0x8000
allí estaría la_start
(que no es así desde el inicio. El archivo S no se toma para compilación) o al menos la función void main (void). Esto sucede debido a la-O2
optimización de GCC. En GCC, con niveles de optimización más altos, las funciones se reordenan. Cuando apagué la optimización (-O0
), luego en la dirección0x8000
, el principal estaba presente.Puede leer sobre el reordenamiento de funciones aquí
Resumen: el código actual es solo una solución. Problema principal a resolver: ¿por qué _start no se llama desde el inicio S? Si esto se soluciona, en la dirección
0x8000 _start
vendría. Con esto no tenemos que preocuparnos por el orden de las funciones realizado por GCC durante una optimización más alta.También hay un video de demostración de mi lado como prueba. Aunque las tasas de parpadeo del LED son diferentes y periódicas en el código, dado que todos los núcleos intentan escribir en los mismos registros GPIO, hay algunos conflictos que hacen que los LED parpadeen a intervalos aleatorios.
fuente
htop
es una herramienta de tierra de usuario basada en * nix. En Linux solo obtiene su información del núcleo a través de/proc
. Esto es material de metal desnudo. No hay ningún núcleo para consultar.