Portabilidad del kernel de Linux

Portabilidad del kernel de Linux

Ocupado con los artículos, no tengo tiempo para escribir un blog y tomar notas. No quiero escribir artículos los viernes y registrar los siguientes libros recientes sobre el kernel de Linux.

Proceso de arranque del kernel de Linux

Antes de trasplantar Linux, primero comprenda su proceso de arranque. El proceso de arranque de Linux se divide en dos partes: el proceso de arranque relacionado con la arquitectura / placa de desarrollo y el posterior proceso de arranque general . La siguiente figura muestra el proceso de inicio del kernel de Linux vmlinux en el procesador de arquitectura ARM. La razón para enfatizar vmlinux es que los núcleos de otros formatos tendrán algunas operaciones únicas antes de realizar los mismos procesos que vmlinux. Por ejemplo, correspondiente al kernel comprimido zImage, primero se autoextrae para obtener vmlinux y luego ejecuta vmlinux para iniciar el proceso de inicio "normal".
La fase de arranque generalmente se escribe en lenguaje ensamblador, primero verifica si el kernel es compatible con el procesador de la arquitectura actual y luego verifica si es compatible con la placa de desarrollo actual. Después de pasar la verificación, está listo para llamar a la función start_kernel de la siguiente etapa. Esto se divide principalmente en los siguientes dos pasos:

  • (1) La dirección virtual que se utiliza al conectarse al kernel, por lo que es necesario configurar la tabla de páginas y habilitar MMU.
  • (2) Trabajo de rutina antes de llamar a la función C start_kernel, incluyendo copiar el segmento de datos, borrar el segmento BSS y llamar a la función start_kernel.
    El código clave de la segunda etapa está escrito principalmente en lenguaje C. Realiza todo el trabajo de inicialización del kernel, y finalmente llama a la función rest_init para iniciar el proceso init, creando el primer proceso del sistema: el proceso init. En la segunda etapa, todavía hay algunos códigos relacionados con la arquitectura / placa de desarrollo. Como se muestra en la siguiente figura, la función setup_arch se utiliza para establecer la configuración relacionada con la arquitectura / placa de desarrollo (como restablecer la tabla de páginas, configurar el reloj del sistema, inicializar el puerto serie, etc.).
    Inserte la descripción de la imagen aquí

Modifique el kernel para admitir la placa de desarrollo S3C2410 / S3C2440

  • Primero configure y compile el kernel para asegurarse de que se pueda compilar correctamente. Después de obtener el código fuente del kernel, primero modifique el Makefile de nivel superior
185 ARCH ?= $(SUBARCH)
186 CROSS_COMPILE ?=
改为
185 ARCH ?= arm
186 CROSS_COMPILE ?= arm-linux-
  • Luego ejecute el siguiente comando, use el archivo arch / arm / configs / S3C2410_defconfig para configurar el kernel, genera el archivo de configuración .config, y luego puede usar directamente "make menuconfig" para modificar la configuración
make smdk2401_defconfig
  • Finalmente compile y genere el kernel, ejecute "make" para generar el archivo de imagen del kernel vmlinux en el directorio superior; ejecute "make uImage" además de generar vmlinux, pero también genere el archivo de imagen del kernel en formato U-Boot uImage en el directorio arch / arm / boot /. Usamos "make uImae"
  • Para la placa de desarrollo S3C2410, se puede utilizar uImage generada anteriormente. Utilice los siguientes comandos en la interfaz de control de U-Boot para descargar uImage e iniciarlo:
tftp 0x32000000 uImage 或 nfs 0x30000000 192.168.10.109:/work/nfs_root/uImage
bootm 0x32000000
  • Pero para la placa de desarrollo S3C2410, use el mismo comando para iniciar uImage, y después de imprimir la siguiente información (tenga en cuenta que la información se imprime cuando se descomprime el archivo misc.c del kernel), aparecen muchos caracteres confusos, como se muestra a continuación:
Start kernel........
Uncompressing Linux..................................done
,booting the kernel

Por lo tanto, Linux 2.6.22.6 no es compatible con la placa de desarrollo S3C2440 utilizada en este libro. Se necesitan algunas modificaciones. En cuanto a qué archivos modificar, debe comprender el código de inicio del kernel.

El kernel inicia el proceso de llamada de función de la segunda etapa (tome la placa de desarrollo S3C2440 como ejemplo). Las funciones con la misma sangría indican que se llaman en la misma función:

start_kernel ->
	setup_arch ->
		setup_processor
		setup_machine
		...
		parse_tags
		...
		parse_cmdline
		paging_init ->
			devicemaps_init ->
				mdesc->map_io() ->
					s3c24xx_init_io
					s3c24xx_init_clocks
					s3c24xx_init_uarts
		...
		console_init ->
			s3c24xx_serial_initconsole
				register_console(&s3c24xx_serial_console)
				...

Modificar el kernel

  • Realice los siguientes cambios en arch / arm / mach-s3c2440 / mach-smdk2440.c:
//修改前
s3c24xx_init_clocks(16934400);

//修改后
s3c24xx_init_clocks(12000000);

  • Luego ejecute make uImage para generar uImage. Para las placas de desarrollo S3C2410 y S3CC2440, se puede utilizar la uImage generada anteriormente.
    Coloque uImage en el directorio del servidor tftp, o en el directorio / work / nfs_root en Linux, y luego use los siguientes comandos en la interfaz de control U-Boot para descargar uImage e iniciarlo.
tftp 0x32000000 uImage 或 nfs 0x30000000 192.168.10.109:/work/nfs_root/uImage
bootm 0x32000000
  • Puede ver la información de arranque del kernel y finalmente aparece la información de pánico (esto requiere modificar la partición mtd y agregar soporte para el sistema de archivos yaffs)

Modificar la partición MTD

MTD (Memory Technology Device), o dispositivo de tecnología de memoria, es una capa de dispositivo extraída de ROM, NOR Flash, NAND Flash y otros dispositivos de almacenamiento en LInux. Proporciona una interfaz de acceso unificada: lectura, escritura, borrado, etc. Se explica el funcionamiento del hardware subyacente y la diferencia entre varios dispositivos de almacenamiento. Gracias a la función del dispositivo MTD, es muy sencillo volver a particionar el NAND Flash.

El proceso de reconocimiento del dispositivo por parte del conductor.

Cuando el controlador reconoce el dispositivo, existen los dos métodos siguientes:
(1) El controlador en sí tiene información del dispositivo, como la dirección de inicio, el número de interrupción, etc .; cuando se carga el controlador, el dispositivo se puede identificar en función de esta información
(2) Controlador No hay información del dispositivo, pero el kernel (o posterior) ha determinado mucha información del dispositivo de acuerdo con otros métodos; al cargar el controlador, compare el controlador con estos dispositivos uno por uno para determinar si los dos coinciden (mach). Si el controlador coincide con un dispositivo, el controlador puede operar el dispositivo.
El segundo método se usa a menudo en el kernel para identificar el dispositivo, que puede administrar centralmente el dispositivo en un archivo. Cuando se cambia la configuración de la placa de desarrollo, es fácil modificar el código.
En el archivo del kernel include / linux / platform_device.h , se definen dos datos Estructura para representar estos dispositivos y controladores: la estructura platform_device se usa para describir el nombre, la ID y los recursos ocupados por el dispositivo (como la dirección / tamaño de la memoria, el número de interrupción), etc .; la estructura platform_driver se usa para describir varias funciones operativas, como las funciones de enumeración , Elimine la función del dispositivo, el nombre del controlador, etc.
Después de que se inicia el kernel, primero construya una lista vinculada para organizar la estructura platform_device que describe el dispositivo para obtener una lista de dispositivos; cuando cargue la estructura platform_driver de un determinado controlador , use algunas funciones coincidentes para verificar si el controlador puede admitir estos dispositivos. Verificaciones comunes El método es simple: compare el nombre del controlador y el dispositivo.

Modificar la partición MTD

Para cambiar la partición, modifique la estructura smdk_default_nand_part en el archivo arch / arm / plat-s3c24xx / common-smdk.c. La NAND Flash se divide en 3 particiones: los primeros 2 MB se utilizan para almacenar el kernel, los siguientes 8 MB se utilizan para almacenar el sistema de archivos JFFS2 y el resto se utiliza para almacenar el sistema de archivos YAFFS.

static struct mtd_partition smdk_default_nand_part[] = {
    
    
    [0] = {
    
    
        .name   = "kernel",
        .size   = SZ_2M,
        .offset = 0,
    },  
    [1] = {
    
     
        .name   = "jffs2",
        .offset = MTDPART_OFS_APPEND,
        .size   = SZ_8M,
    },  
    [2] = {
    
     
        .name   = "yaffs",
        .offset = MTDPART_OFS_APPEND,
        .size   = MTDPART_SIZ_FULL,
    },  
};

Entre ellos, MTDPART_OFS_APPEND indica que la partición actual sigue inmediatamente a la partición anterior, y MTDPART_SIZ_FULL indica que el tamaño de la partición actual es el espacio Flash restante.
Luego ejecute make uImage para regenerar el kernel

Migrar el sistema de archivos YAFFS

YAFFS (otro sistema de archivos flash) es un sistema integrado similar a los scripts en JFFS / JFFS2, especialmente diseñado para NAND Flash, adecuado para dispositivos de almacenamiento de gran capacidad.

Hay dos pasos para trasplantar yaffs:

  • Agregue el código yaffs2 al kernel.
    Esto se puede parchear en el kernel a través del archivo de script patch-ker.sh en el directorio yaffs2
  • Configurar y compilar el kernel

Finalmente ejecute make uImage para compilar el kernel

Supongo que te gusta

Origin blog.csdn.net/qq_41782149/article/details/103520415
Recomendado
Clasificación