Red de conocimiento informático - Conocimiento informático - ¿Cómo ajustar la secuencia de inicialización del controlador cuando se inicia el kernel de Linux?

¿Cómo ajustar la secuencia de inicialización del controlador cuando se inicia el kernel de Linux?

Pregunta Lo que intento lograr aquí es utilizar el ID del chip como la dirección MAC de la tarjeta de red cuyo controlador es enc28j60_init. Sin embargo, la función para leer el ID del chip está en el módulo as352x_afe_init, por lo que primero se debe inicializar as352x_afe_init. En este ejemplo, una vez completada la compilación del kernel, puede ver que enc28j60_init está antes de as352x_afe_init en el mapa del sistema generado (system.map), por lo que el mapa del chip (system.map) no se puede leer. Puede ver que enc28j60_init está antes. as352x_afe_init. Por lo tanto, no se puede leer el ID del chip. Entonces, nuestro objetivo es inicializar el controlador as352x_afe_init antes de enc28j60_init, luego leer la ID del chip y configurar la ID del chip en la MAC de la NIC al inicializar la tarjeta de red. El ID del chip se establece en la dirección MAC de la tarjeta de red.

Solución

1

La forma más sencilla es cambiar el orden de los dispositivos en la lista de dispositivos del kernel

archarmmach-as352xcore. c

enc28j60_init corresponde a ssp_device porque la inicialización de la NIC utiliza el controlador SPI para comunicarse con él.

as352x_afe_init corresponde a afe_device.

Así es:

Cambie afe a la parte superior:

Sin embargo, el resultado real es que no hay ningún efecto, incluso después de generar systemp.map. , el orden de inicialización del módulo Nada ha cambiado tampoco. Esto significa que cambiar el orden de la lista de dispositivos en core.c es inútil si desea implementar un cambio en el orden de carga de los controladores.

Puedes enviar un mensaje privado al kernel para obtener más vídeos tutoriales y documentación del kernel de Linux de forma gratuita.

Código fuente del kernel de Linux/ajuste de memoria/sistema de archivos/gestión de procesos/controlador de dispositivo/video tutorial de aprendizaje de pila de protocolos de red-Tencent Classroom

2

I Vi muchas publicaciones en Internet y lo dejaron muy claro.

El kernel de Linux define una serie de macros que corresponden a las diferentes prioridades de diferentes controladores en el orden de carga. Macros:

includelinuxinit.h

Después de usar estas macros para definir los nombres de funciones de sus propios controladores, se cargarán primero en un orden de carga diferente.

El module_init que usamos para escribir el controlador corresponde a #define module_init(x) __initcall(x); y #define __initcall(fn) device_initcall(fn), por lo que la prioridad de carga del controlador es 6.

En las diferentes macros anteriores, puedes definir diferentes prioridades de carga. >

Entre las diferentes prioridades mencionadas anteriormente, cuanto menor sea el número, mayor será la prioridad. El orden de carga de los conductores con la misma prioridad está determinado por el proceso de vinculación y el resultado no está definido, por lo que no podemos establecer manualmente quién llega primero y quién llega último. El orden en el que se cargan los controladores con diferentes prioridades está determinado por el proceso de vinculación y los resultados no están definidos, por lo que no podemos establecer manualmente quién aparece primero.

Entonces, tal como hicimos antes con el controlador:

Así todos se inicializan con la misma prioridad.

Finalmente, en el sistema resultante, la carga El orden de estos controladores se puede ver en el directorio raíz. Mapa:

Desde c0019920 t __initcall_ i2c_dev_init6 c0019924 t __initcall_as352x_afe_i2c_init6 c0019928 t __initcall_as352x_afe_init6 en c00198e4 t __initcall_enc28j60_init 6 antes, entonces sucedió lo siguiente, así que tuve que hacer modificaciones aquí. Después de comprender el principio, lo único que se me ocurre es cambiar as352x_afe_init para que tenga un nivel de prioridad sobre enc28j60_init, que es prioridad 5, es decir, llamar a: fs_initcall(as352x_afe_init) en el controlador o cambiar enc28j60_init después de as352x_afe_init, que es prioridad; 7, es decir, llame a: fs_initcall(as352x_afe_init) en el controlador o cambie enc28j60_init después de enc28j60_afe_init; Es decir, la prioridad es 7, es decir, llamar a: late_initcall (enc28j60_init) en el controlador; pero el problema aquí es que si cambia as352x_afe_init al primer nivel antes de enc28j60_init, encontrará que enc28j60_init se inicializa mediante la tarjeta de red posterior. Aunque el ID del chip se lee correctamente, hay un problema con el IP-auto detrás de él. Entonces me di por vencido. Si enc28j60_init se cambia a as352x_afe_init, sin embargo, desde system.map, podemos ver el controlador con prioridad 7. Obviamente hay varios controladores, que también están relacionados con la inicialización de la tarjeta, por lo que después de este cambio, después de intentarlo, todavía falla. Por lo tanto, no hay forma de simplemente reordenar los controladores existentes. Finalmente, nos vimos obligados a encontrar una manera de satisfacer nuestras necesidades, que era definir una prioridad separada y colocar allí todas las inicializaciones relacionadas con afe, para garantizar que no haya otros conflictos relacionados. Al final, éste resultó ser el camino a seguir.

Los pasos para agregar una nueva prioridad son los siguientes: 1. Definir la nueva prioridad, incluyendo includelinuxinit.h:

2. Definir nuestro controlador usando la nueva macro correspondiente:

p>

Completamos la definición aquí y pensamos que no habría ningún problema, pero después de la compilación, encontramos que la función con prioridad 7 se colocó al final de system.map en lugar de colocarse primero como esperado. Después del nivel 7 y

antes. Finalmente, también encontramos que la macro en el archivo de enlace correspondiente no se agregó:

3. includeasm-genericvmlinux.lds.h

Finalmente, después de recompilar, podemos encontrar qué Lo que queremos es coherente con la inicialización del controlador relacionado con Afe que se encuentra antes de enc28j60_init de la tarjeta de red. Además, se puede leer el ID del chip dentro de la tarjeta de red. Por supuesto, correspondiente al archivo system.map generado por la compilación y al controlador definido a través de module_init, la prioridad pasa a ser 7. La prioridad correspondiente de late_initcall es 8.

Nota: La placa de desarrollo actual es una placa arm, por lo que el script de carga correspondiente es:

linux-2.6.28.4archarmkernelvmlinux.lds. Se parece a este archivo: linux-2.6.28.4archarmkernelvmlinux.lds.S Generar el guión anterior. Esta línea en vmlinux.lds:

es una línea que expande la función init correspondiente a la línea anterior y la coloca en esta ubicación.

3 Sin embargo, al final del día, descubrí que la tarjeta de red todavía no funcionaba correctamente. Al día siguiente, descubrí inesperadamente que la configuración de la dirección de la tarjeta de red hacía que la tarjeta de red no funcionara correctamente. . En otras palabras, sólo necesitas establecer afe en el nivel de prioridad original 5, en lugar de tener que tomarte muchos problemas para cambiar cosas en el sistema...

Pero al menos esta es una solución alternativa. método, aunque el efecto no es el ideal...