嵌入式Linux移植之initramfs

时间:2022-02-12 08:31:52

        Linux可以将根文件系统编译进内核,称作initramfs。加载内核的时候,真实的内核和根文件系统都加载到内存。这在嵌入式系统中非常普遍,我们通常制作一个最小根文件系统initramfs,并把他编译进内核。而把其他的内容制作成其他的文件系统,系统启动时再挂载到根文件系统的某个根目录下。initramfs另外一个好处是,其可以和内核一起加载到内存,方便早期的调试。由于在内存中,所以一般只需要实现中断,时钟和串口就可以正常启动系统。

        本文基于EasyLinux平台移植Linux系统到GT2440开发板上,EasyLinux平台是基于Buildroot定制的编译系统,详情可以参见《嵌入式Linux编译系统的设计》一文,我的内核版本为Linux3.18.6。

        首先进行package的配置,在buildroot目录下:

        make O=build/gt2440 menuconfig

嵌入式Linux移植之initramfs

选中cpio和initial ram filesystem linked into linux kernel。可以在cpio中定制根文件系统,这里暂不说明如何定制文件系统,只讲解如何制作一个initramfs。

嵌入式Linux移植之initramfs

然后配置内核:

         make O=build/gt2440 linux-menuconfig

嵌入式Linux移植之initramfs

嵌入式Linux移植之initramfs

同样选中initramfs,至此,相关配置已经完成。只需要完成内核移植,即可以启动系统。要启动initramfs,需要至少实现中断,时钟和串口驱动。我用的GT2440实际上内核已经完全支持(mach-smdk2440),因此所做的工作非常少,只需要把时钟源修改成12MHz就好了。在mach-smdk2440.c中

static void __init smdk2440_init_time(void)
{
	//s3c2440_init_clocks(16934400);
        s3c2440_init_clocks(12000000);
	samsung_timer_init();
}

此外,还需要把串口驱动编译进内核,我刚开始就是这里坑了一下:

嵌入式Linux移植之initramfs

嵌入式Linux移植之initramfs
这里说明一下如何确定console=xxxx名字,在drivers/tty/serial/samsung.c中s3c24xx_serial_probe函数

	if (!s3c24xx_uart_drv.state) {
		ret = uart_register_driver(&s3c24xx_uart_drv);
		if (ret < 0) {
			pr_err("Failed to register Samsung UART driver\n");
			return ret;
		}
	}
这里注册了串口驱动,而驱动的名字在s3c24xx_uart_drv中

static struct uart_driver s3c24xx_uart_drv = {
	.owner		= THIS_MODULE,
	.driver_name	= "s3c2410_serial",
	.nr		= CONFIG_SERIAL_SAMSUNG_UARTS,
	.cons		= S3C24XX_SERIAL_CONSOLE,
	.dev_name	= S3C24XX_SERIAL_NAME,
	.major		= S3C24XX_SERIAL_MAJOR,
	.minor		= S3C24XX_SERIAL_MINOR,
};
S3C24XX_SERIAL_NAME为字符串ttySAC,则第一个串口为ttySAC0。
接下来就是编译了,事实上内核支持直接编译出uImage镜像,但本人测试发现,编出来的uImage镜像虽然可以正常启动系统,但是启动时打印内核是不压缩的,明明配置了内核是gzip压缩,原因不明。嵌入式系统通常需要节约flash空间,内核是必须要压缩的。因此,我决定先编译出普通的Image镜像,即不压缩的内核。然后自己压缩内核制作uImage镜像。

配置:

         make O=build/gt2440 menuconfig

嵌入式Linux移植之initramfs

选custom内核镜像,名字为Image。即编译内核的时候target为Image。

嵌入式Linux移植之initramfs

编译:make O=build/gt2440

制作uImage镜像:

make O=build/gt2440 easylinux-mkimage

easylinux-mkimage:
	rm -rf $(TOPDIR)/image/*
	cp -rf $(BINARIES_DIR)/* $(TOPDIR)/image
	./easylinux_mkimage.sh $(HOST_DIR) $(TOPDIR)/image

#!/bin/sh
echo "gzip -9 Image"
gzip -9 $2/Image
$1/usr/bin/mkimage -A arm -O linux -T kernel -C gzip -a 0x30008000 -e 0x30008000 -n "easylinux" -d $2/Image.gz $2/uImage
uboot启动参数设置:

bootargs=console=ttySAC0,115200n8 mem=62M

下载内核:

嵌入式Linux移植之initramfs

嵌入式Linux移植之initramfs
启动系统,注意这里,内核是gzip压缩的。

嵌入式Linux移植之initramfs

嵌入式Linux移植之initramfs
成功启动系统:

嵌入式Linux移植之initramfs

嵌入式Linux移植之initramfs

至此,我们只需要download到内存就完全启动了系统。

大家可以跳过uImage镜像的自己制作,直接编译出uImage镜像,也是可以启动的。我这里不知道什么原因,内核总是不会压缩,知道的朋友可以告诉我。

附一个我自己直接编译uImage镜像的截图,内核是非压缩的。(内核是有配置CONFIG_KERNEL_GZIP的)

嵌入式Linux移植之initramfs


嵌入式Linux移植之initramfs