您的位置:首页 > 运维架构 > Linux

Linux-2.6.32.2内核在mini2440上的移植(一)---构建自主开发环境

2012-04-07 15:34 573 查看


Linux-2.6.32.2内核在mini2440上的移植(一)---构建自主开发环境

移植环境(红色粗字体字为修改后内容,蓝色粗体字为特别注意内容)

1,主机环境:VMare下Fedora10 ,1G内存。

2,编译编译环境:arm-linux-gcc v4.4.3,arm-none-linux-gnueabi-gcc v4.5.1。

3,开发板:mini2440,4M nor flash,64M nand flash。

4,linux 版本:linux-2.6.32.2

5,参考文章:

【1】嵌入式linux应用开发完全手册,韦东山,编著。
【2】http://blogold.chinaunix.net/u3/101649/showart_2276906.html
【3】Mini2440 之Linux 移植开发实战指南
1.1,构建自主开发环境

我们在进行u-boot移植时,在u-boot-2009.08在mini2440上的移植(六)---增加引导内核功能提到过机器码(MACH_TYPE),在引导测试时,为了便于测试,使用的是友善官方移植好的linux内核。现在我们将从这里着手,逐步开始linux内核的移植。

【1】下载并解压内核源码

在命令行终端中可以通过下列方式下载,当然用其它下载工具下载

[root@localhost ~]# wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.32.2.tar.gz

然后解压:

[root@localhost ~]# cd ./linux-test/

[root@localhost linux-test]# tar -zxf ../linux-2.6.32.2.tar.gz

[root@localhost linux-test]# ls

linux-2.6.32.2 linux-2.6.39 yaffs2 yaffs2.tar.gz

[root@localhost linux-test]# cd linux-2.6.32.2

[root@localhost linux-2.6.32.2]#

【2】指定交叉编译变量

我们移植目的是让 Linux-2.6.32.2 可以在mini2440 上运行。首先,我们要使得Linux-2.6.32.2 的缺省目标平台成为ARM 的平台,修改总目录下的Makefile。

用gedit打开/Makefile,定位到183行,修改如下:

# Alternatively CROSS_COMPILE can be set in the environment.

# Default value for CROSS_COMPILE is not to prefix executables

# Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile

export KBUILD_BUILDHOST := $(SUBARCH)

ARCH ?= arm

CROSS_COMPILE ?= arm-linux-


# Architecture as present in compile.h

其中,ARCH 是指定目标平台为arm,CROSS_COMPILE 是指定交叉编译器,这里指定的是系统默认的交叉编译器,如要使用其它的,则要把编译器的全路径在这里写出。注意,在arm和arm-linux-后不要留空格,否则在编译时会出现错误。

接下来,要测试一下linux 的编译是否能正常通过。执行:

[root@localhost linux-2.6.32.2]# make s3c2410_defconfig

使用缺省内核配置文件,s3c2410_defconfig 是SMDK2440 的缺省配置文件

[root@localhost linux-2.6.32.2]# make

编译时间较长... ... 。编译通过,在此我们先不必烧写到开发板验证它的正确性。

【3】建立自己的目标平台

(1)关于机器码

以上编译是用的 Linux 内核本身支持的目标平台配置,它对应于SMDK2440。现在我们要参考SMDK2440 加入自已的开发板平台,我们使用的是mini2440,因此取名为MINI2440。需要说明的是,Linux-2.6.32.2 本身已经包含了mini2440 的支持,这样就出现了重名。那怎么办呢?在此我们依然使用MINI2440 这个名称,只不过在后面的移植步骤中,把原始内核自带的mini2440 代码部分直接删除就可以了,以免和我们自己移植的混淆。

首先,很关键的一点,内核在启动时,是通过bootloader 传入的机器码(MACH_TYPE)确定应启动哪种目标平台的,友善之臂已经为mini2440 申请了自己的机器码为1999,它位于linux-2.6.32.2/arch/arm/tools/mach_types 文件中,如下面所示:

打开/arch/arm/tools/mach-types,定位到1989行,可以看到文件中有相应的机器码的定义定义如下(黑体部分):

exeda MACH_EXEDA EXEDA 1994

mx31sf005 MACH_MX31SF005 MX31SF005 1995

f5d8231_4_v2 MACH_F5D8231_4_V2 F5D8231_4_V2 1996

q2440 MACH_Q2440 Q2440 1997

qq2440 MACH_QQ2440 QQ2440 1998

mini2440 MACH_MINI2440 MINI2440 1999

colibri300 MACH_COLIBRI300 COLIBRI300 2000

jades MACH_JADES JADES 2001

spark MACH_SPARK SPARK 2002

benzina MACH_BENZINA BENZINA 2003

在U-boot/include/asm-arm/mach-types.h 文件的1985行附近(u-boot-2009.08),可以看到mini2440 的机器码定义如下面所示:

#define MACH_TYPE_Q2440 1997

#define MACH_TYPE_QQ2440 1998

#define MACH_TYPE_MINI2440 1999 //mini2440的机器码

#define MACH_TYPE_COLIBRI300 2000

#define MACH_TYPE_JADES 2001

这需要两者相匹配,如果内核的机器码和bootloader 传入的不匹配,就会经常出现下面的错误:

Uncompressing Linux................................................................................................................................. done, booting

the kernel.

运行到这不就停住了。

接下来, 我们注意到linux-2.6.32.2/arch/arm/mach-s3c2440 目录下有个mach-mini2440.c 文件,它其实就是国外爱好者为mini2440 移植添加的主要内容了,但我们不用它,把它直接删除。将linux-2.6.32.2/arch/arm/mach-s3c2440/目录下的mach-smdk2440.c 复制一份。命名为mach-mini2440.c ,并打开文件定位到末尾处,找到

MACHINE_START(S3C2440, "SMDK2440") , 将其修改为

MACHINE_START(MINI2440, "Mini2440 development board")

提示:开发板运行后,在命令行终端输入:cat /proc/cpuinfo 可以看到我们添加的开发板信息,当然这个信息可以定制成我们需要的信息。

(2)修改时钟源频率

在上面我们刚刚复制并修改过的mach-mini2440.c文件中,定位到163行附近,把其中的16934400(代表原SMDK2440 目标板的晶振是16.9344MHz)改为mini2440 开发板上实际使用的12000000(代表mini2440 开发板上的晶振12MHz,元器件标号为X2),如下所示:

static void __init smdk2440_map_io(void)

{

s3c24xx_init_io(smdk2440_iodesc, ARRAY_SIZE(smdk2440_iodesc));

s3c24xx_init_clocks(12000000);

s3c24xx_init_uarts(smdk2440_uartcfgs, ARRAY_SIZE(smdk2440_uartcfgs));

}

(3)从SMDK2440 到MINI2440

因为我们要制作自己的mini2440 平台体系,因此把mach-mini2440.c 中所有的smdk2440 字样改为mini2440,可以使用批处理命令修改,在vim 的命令模式下输入:

%s/smdk2440/mini2440/g

上面这句的意思是:把所有和“smdk2440”匹配的字符串全部替换为“mini2440”,前面的“%s“代表字符串匹配,最后的“g”代表global,是全局的意思,不过这里采用另一种办法,在gedit里用查找替换,比较方便,操作如下:

gedit->搜索->替换,在打开的对话框中,在搜索一栏输入“smdk2440”,在替换为一栏输入“mini2440”然后点击全部替换按钮,即可完成。

除此之外,还有一个地方需要改动,在mini2440_machine_init(void)函数中,把smdk_machine_init()函数调用注释掉,因为我们后面会编写自己的初始化函数,不需要调用smdk2440 原来的,定位到173行,修改如下:

static void __init mini2440_machine_init(void)

{

s3c24xx_fb_set_platdata(&mini2440_fb_info);

s3c_i2c0_set_platdata(NULL);

platform_add_devices(mini2440_devices, ARRAY_SIZE(mini2440_devices));

//smdk_machine_init();

}

(4)编译测试

在 Linux 源代码根目录下执行

[root@localhost linux-2.6.32.2]# make mini2440_defconfig

#

# configuration written to .config

#

[root@localhost linux-2.6.32.2]# make mini2440_defconfig

使用Linux 官方自带的mini2440 配置。

[root@localhost linux-2.6.32.2]# make zImage

编译内核,时间较长,最后会生成zImage。把生成的内核文件zImage(位于arch/arm/boot 目录)下载到板子的内存中运行,可以看到内核已经可以正常启动了,如下所示,但此时大部分硬件驱动还没加,并且也没有文件系统,因此还无法登陆。

... ...

【4】内核配置菜单中的mini2440 选项和实际代码是如何关联的

在开始移植其他驱动之前,我们再了解一些看起来比较“神秘”的常识,那就是运行make menuconfig 时,内核配置菜单中的mini2440 选项是如何出现的。需要确保前面已经执行了make mini2440_defconfig 加载了缺省配置,因为在x86平台下下执行此操作,系统默认的是x86平台,而且还要在顶层Makefile里作了如下修改:

export KBUILD_BUILDHOST := $(SUBARCH)

ARCH ?= arm

CROSS_COMPILE ?= arm-linux-


现在在终端中进入到linux-2.6.32.2根目录下执行:

[root@localhost linux-2.6.32.2]# make menuconfig

出现下图所示内核配置根菜单



按上下箭头键移动到 System Type,按回车进入该子菜单,如图



再找到S3C2440 Machines,按回车进入该子菜单,如图



在此就可以看到 Linux 天生内核对mini2440 开发板的支持选项了,那么它们是从哪里来的呢?

打开 Linux-2.6.32.2/arch/arm/mach-s3c2440/Kconfig 文件定位到99行附近,可以找到如下信息(黑体部分):
config MACH_AT2440EVB

bool "Avantech AT2440EVB development board"

select CPU_S3C2440

select S3C_DEV_USB_HOST

select S3C_DEV_NAND

help

Say Y here if you are using the AT2440EVB development board
config MACH_MINI2440

bool "MINI2440 development board"

select CPU_S3C2440

select EEPROM_AT24

select LEDS_TRIGGER_BACKLIGHT

select SND_S3C24XX_SOC_S3C24XX_UDA134X

select S3C_DEV_NAND

select S3C_DEV_USB_HOST

help

Say Y here to select support for the MINI2440. Is a 10cm x 10cm board

available via various sources. It can come with a 3.5" or 7" touch LCD.

endmenu
现在明白了吧,“MINI2440 development board”正是在这个Kconfig 文件中定义说明的,当然你可以根据自己的喜好改为其他显示信息。这里的显示信息只是在内核配置菜单中出现的,要让选择的配置实际起效,还需要根据此配置在Makefile 中添加相应的代码文件,请看该目录下的Makefile,定位到25行,如下所示:
# Machine support
obj-$(CONFIG_MACH_ANUBIS) += mach-anubis.o

obj-$(CONFIG_MACH_OSIRIS) += mach-osiris.o

obj-$(CONFIG_MACH_RX3715) += mach-rx3715.o

obj-$(CONFIG_ARCH_S3C2440) += mach-smdk2440.o

obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o

obj-$(CONFIG_MACH_AT2440EVB) += mach-at2440evb.o

obj-$(CONFIG_MACH_MINI2440) += mach-mini2440.o
这样,配置文件就跟实际的代码文件通过配置定义联系在一起了,这里的配置定义是“CONFIG_MACH_MINI2440”,内核中还有很多类似的配置定义,并且有的配置定义还存在依赖关系,我们在此就不对它们详细说明了,随着对内核代码结构的不断熟悉,你就会逐渐学会分析和查找你所需要的各种配置和定义等。
【5】移植Nand 驱动并更改分区信息
(1)修改Nand Flash 分区表

系统默认的分区不一定是我们所需的,所以要自已修改,除此之外,还有 Nand Flash的结构信息需要增加填写,以便能够适合系统自带的Nand Flash 驱动接口,这可以参考SMDK2440 中关于Nand Flash 设备注册的一些信息。

打开/arch/arm/plat-s3c24xx/common-smdk.c,定位到110行附近,可以看到这样一个结构体:

static struct mtd_partition smdk_default_nand_part[] = {

[0] = {

.name = "Boot Agent",

.size = SZ_16K,

.offset = 0,

},

[1] = {

.name = "S3C2410 flash partition 1",

.offset = 0,

.size = SZ_2M,

},

[2] = {

.name = "S3C2410 flash partition 2",

.offset = SZ_4M,

.size = SZ_4M,

},

[3] = {

.name = "S3C2410 flash partition 3",

.offset = SZ_8M,

.size = SZ_2M,

},

[4] = {

.name = "S3C2410 flash partition 4",

.offset = SZ_1M * 10,

.size = SZ_4M,

},

[5] = {

.name = "S3C2410 flash partition 5",

.offset = SZ_1M * 14,

.size = SZ_1M * 10,

},

[6] = {

.name = "S3C2410 flash partition 6",

.offset = SZ_1M * 24,

.size = SZ_1M * 24,

},

[7] = {

.name = "S3C2410 flash partition 7",

.offset = SZ_1M * 48,

.size = SZ_16M,

}

};

这其实就是Nand Flash 的分区表,在Linux-2.6.32.2 中,nand 驱动是被注册为平台设备的,这同样可在这个文件的166行看到如下信息:

static struct s3c2410_platform_nand smdk_nand_info = {

.tacls = 20,

.twrph0 = 60,

.twrph1 = 20,

.nr_sets = ARRAY_SIZE(smdk_nand_sets),

.sets = smdk_nand_sets,

};

参考以上结构信息,我们也在自己的mach-mini2440.c 中照此添加实现,同时需要参考友善之臂原厂内核中的Nand 分区表,操作如:

打开/arch/arm/mach-s3c2440/mach-mini2440.c,定位到151行处,将下面更改后的分区表定义结构加入其中:

.lpcsel = ((0xCE6) & ~7) | 1<<4,

};

/* NAND parititon from 2.4.18-swl5 */

static struct mtd_partition mini2440_default_nand_part[] = {

[0] = {

.name = "boot",
//;这里是bootloader 所在的分区,可以放置u-boot, supervivi 等内容,对应/dev/mtdblock0

.offset = 0,

.size = 0x00040000, //256K

},

[1] = {

.name = "param",
//;这里是supervivi 的参数区,其实也属于bootloader 的一部分,如果u-boot 比较大,可以把此区域覆盖掉,不会影响系统启动,对应/dev/mtdblock1

.offset = 0x00040000,

.size = 0x00020000,

},

[2] = {

.name = "kernel",
//;内核所在的分区,大小为5M,足够放下大部分自己定制的巨型内核了,比如内核使用了更大的Linux Logo 图片等,对应/dev/mtdblock2

.offset = 0x00060000,

.size = 0x00500000,

},

[3] = {

.name = "rootfs",
//;文件系统分区,友善之臂主要用来存放yaffs2 文件系统内容,对应/dev/mtdblock3

.offset = 0x00560000,

.size = 1024 * 1024 * 1024,

},

[4] = {

.name = "nand",
//;此区域代表了整片的nand flash,主要是预留使用,比如以后可以通过应用程序访问读取/dev/mtdblock4 就能实现备份整片nand flash 了。

.offset = 0x00000000,

.size = 1024 * 1024 * 1024,

}

};


//;这里是开发板的nand flash 设置表,因为板子上只有一片,因此也就只有一个表

static struct s3c2410_nand_set mini2440_nand_sets[] = {

[0] = {

.name = "NAND",

.nr_chips = 1,

.nr_partitions = ARRAY_SIZE(mini2440_default_nand_part),

.partitions = mini2440_default_nand_part,

},

};


/* choose a set of timings which should suit most 512Mbit

* chips and beyond.

*/

//;这里是nand flash 本身的一些特性,一般需要对照datasheet 填写,大部分情况下按照以下参数填写即可

static struct s3c2410_platform_nand mini2440_nand_info = {

.tacls = 20,

.twrph0 = 60,

.twrph1 = 20,

.nr_sets = ARRAY_SIZE(mini2440_nand_sets),

.sets = mini2440_nand_sets,

.ignore_unset_ecc = 1,

};

除此之外,还需要把nand flash 设备注册到系统中

static struct platform_device *mini2440_devices[] __initdata = {

&s3c_device_usb,

&s3c_device_lcd,

&s3c_device_wdt,

&s3c_device_i2c0,

&s3c_device_iis,

&s3c_device_nand, //;把nand flash 设备添加到开发板的设备列表结构

};

(3)加入编译头文件

在上面的文件中定位到50行附近,加入一下头文件:

#include <linux/mtd/mtd.h>

#include <linux/mtd/nand.h>

#include <linux/mtd/nand_ecc.h>

#include <linux/mtd/partitions.h>

#include <plat/nand.h>


(4)传入mini2440_nand_info结构体初始化参数

定位到223行附近,修改如下:

static void __init mini2440_machine_init(void)

{

s3c_i2c0_set_platdata(NULL);

s3c_device_nand.dev.platform_data = &mini2440_nand_info;

platform_add_devices(mini2440_devices, ARRAY_SIZE(mini2440_devices));

//smdk_machine_init();

}

然后保存。

1.2,编译测试

至此,就完成了nand flash 驱动的移植,修改完成之后,最好在每次进行make menuconfig后都有执行

[root@localhost linux-2.6.32.2]# make clean

因为内核中已经可能已经增减了要编译的模块,所以要在编译之前清除下已编译的目标模块,不然可能编译出错,然后进行编译:

[root@localhost linux-2.6.32.2]# make zImage

编译完成后,生成zImage文件,然后给开发板上电,然后把zImage烧写到开发板里,看到如下信息:

S3C24XX NAND Driver, (c) 2004 Simtec Electronics

s3c24xx-nand s3c2440-nand: Tacls=3, 29ns Twrph0=7 69ns, Twrph1=3 29ns

s3c24xx-nand s3c2440-nand: NAND soft ECC

NAND device: Manufacturer ID: 0xec, Chip ID: 0xf1 (Samsung NAND 128MiB 3,3V 8-bit)

Scanning device for bad blocks

Creating 5 MTD partitions on "NAND 128MiB 3,3V 8-bit":

0x000000000000-0x000000040000 : "boot"

uncorrectable error :

0x000000040000-0x000000060000 : "param"

ftl_cs: FTL header not found.

0x000000060000-0x000000560000 : "kernel"

ftl_cs: FTL header not found.

0x000000560000-0x000040560000 : "root"

mtd: partition "root" extends beyond the end of device "NAND 128MiB 3,3V 8-bit"

-- size truncated to 0x7aa0000

ftl_cs: FTL header not found.

0x000000000000-0x000040000000 : "nand"

mtd: partition "nand" extends beyond the end of device "NAND 128MiB 3,3V 8-bit"

-- size truncated to 0x8000000

uncorrectable error :

dm9000 Ethernet Driver, V1.31

ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver

s3c2410-ohci s3c2410-ohci: S3C24XX OHCI

s3c2410-ohci s3c2410-ohci: new USB bus registered, assigned bus number 1

s3c2410-ohci s3c2410-ohci: irq 42, io mem 0x49000000

usb usb1: configuration #1 chosen from 1 choice

hub 1-0:1.0: USB hub found

hub 1-0:1.0: 2 ports detected

可以在启动时看到如图蓝色信息,它们正是我们刚刚添加的nand flash 分区信息,以及开发板本身nand flash 的一些信息,这里可以看到是128M 的nand flash。

.. ....

rpcbind: server 10.1.0.128 not responding, timed out

Root-NFS: Unable to get nfsd port number from server, using default

Looking up port of RPC 100005/1 on 10.1.0.128

rpcbind: server 10.1.0.128 not responding, timed out

Root-NFS: Unable to get mountd port number from server, using default

Root-NFS: Server returned error -5 while mounting /nfsboot

VFS: Unable to mount root fs via NFS, trying floppy.

VFS: Cannot open root device "nfs" or unknown-block(2,0)

Please append a correct "root=" boot option; here are the available partitions:

1f00 256 mtdblock0 (driver?)

1f01 128 mtdblock1 (driver?)

1f02 5120 mtdblock2 (driver?)

1f03 125568 mtdblock3 (driver?)

1f04 131072 mtdblock4 (driver?)

Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(2,0)

[<c002e9c0>] (unwind_backtrace+0x0/0xd8) from [<c02d4798>] (panic+0x40/0x118)

[<c02d4798>] (panic+0x40/0x118) from [<c0008e68>] (mount_block_root+0x1c8/0x208)

[<c0008e68>] (mount_block_root+0x1c8/0x208) from [<c00090fc>] (prepare_namespace

+0x160/0x1b8)

[<c00090fc>] (prepare_namespace+0x160/0x1b8) from [<c0008434>] (kernel_init+0xd8

/0x10c)

[<c0008434>] (kernel_init+0xd8/0x10c) from [<c002a868>] (kernel_thread_exit+0x0/

0x8)

这里提示的挂在分区时出现了问题。

解决办法:

在分区中可以把下面的代码去掉:

[b] [1] = {

.name = "param",
//;这里是supervivi 的参数区,其实也属于bootloader 的一部分,如果u-boot 比较大,可以把此区域覆盖掉,不会影响系统启动,对应/dev/mtdblock1

.offset = 0x00040000,

.size = 0x00020000,

},

[/b]根据不同情况而定,出现上面的原因也有可能是没有为linux-2.6.32.2添加yaffs文件系统。

摘自:http://www.cnblogs.com/hnrainll/archive/2011/06/09/2076138.html

接下来,将为linux-2.6.32.2添加yaffs文件系统。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐