fl2440内核移植过程Linux-3.0

时间:2021-04-11 16:32:25

下载并解压缩linux-3.0.tar.bz2 源代码

[luminqi@localhost kernel]$ wget https://www.kernel.org/pub/linux/kernel/v3.0/linux-3.0.tar.bz2

[luminqi@localhost kernel]$tar -xjf linux-3.0.tar.bz2

[luminqi@localhost kernel]$cd linux-3.0

1. 首先修改顶层目录的Makefile文件

这里首要便是交叉编译器环境变量和选择开发平台类型

然后要将生成的zimage拷贝到当前目录,再手动增加mkimage工具来自动把Zimage生成可执行的.bin文。

注:内核编译之后会生成两个文件。一个Image,一个Zimageimage为内核映像文件,而Zimage为内核映像压缩文件。Image大约为4M,而Zimage不到2M

[luminqi@localhost linux-3.0]$ vim  Makefile

178 @@ -192,8 +192,8 @@
179 # Default value for CROSS_COMPILE is not to prefix executables
180 # Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile
181 export KBUILD_BUILDHOST := $(SUBARCH)
182 -ARCH ?= $(SUBARCH)
183 -CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%)
184 +ARCH ?=arm
185 +CROSS_COMPILE ?=/opt/buildroot-2012.08/arm920t/usr/bin/arm-linux-
186
187 # Architecture as present in compile.h
188 UTS_MACHINE := $(ARCH)
189 @@ -558,6 +558,10 @@
190 # Defaults to vmlinux, but the arch makefile usually adds further targets
191 all: vmlinux
192
193 + cp arch/arm/boot/zImage . -f
194 + mkimage -A arm -O linux -T kernel -C none -a 30008040 -n "Linux Kernel" -d zImage linuxrom-s3c2440.bin
195 + rm -f zImage
196 +
197 ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
198 KBUILD_CFLAGS += -Os
199 else
200 @@ -1201,7 +1205,7 @@
201 -o -name '.*.rej' -o -size 0 \
202 -o -name '*%' -o -name '.*.cmd' -o -name 'core' \) \
203 -type f -print | xargs rm -f
204 -
205 + @rm -f linuxrom-s3c2440.bin
206
207 # Packaging of the kernel to various formats


2.修改晶振频率

因为我使用的是FL2440的开发板,根据datesheet可知晶振频率为12M。所以下一步修改晶振频率

[luminqi@localhost linux-3.0]$vim arch/arm/mach-s3c2440/mach-smdk2440.c

 

53 @@ -155,12 +190,13 @@
54 &s3c_device_wdt,
55 &s3c_device_i2c0,
56 &s3c_device_iis,
57 + &s3c_device_dm9000,
58 };
59
60 static void __init smdk2440_map_io(void)
61 {
62 s3c24xx_init_io(smdk2440_iodesc, ARRAY_SIZE(smdk2440_iodesc));
63 - s3c24xx_init_clocks(16934400);
64 + s3c24xx_init_clocks(12000000);
65 s3c24xx_init_uarts(smdk2440_uartcfgs, ARRAY_SIZE(smdk2440_uartcfgs));
66 }
67

3. 修改驱动的串口

[luminqi@localhost linux-3.0]$vim drivers/tty/serial/samsung.c

154 @@ -54,7 +54,7 @@
155
156 /* UART name and device definitions */
157
158 -#define S3C24XX_SERIAL_NAME "ttySAC"
159 +#define S3C24XX_SERIAL_NAME "ttyS"
160 #define S3C24XX_SERIAL_MAJOR 204
161 #define S3C24XX_SERIAL_MINOR 64
162


[luminqi@localhost linux-3.0]$cp arch/arm/configs/mini2440_defconfig .config

[luminqi@localhost linux-3.0]$ ll .config
-rw-rw-r--. 1 luminqi luminqi 57270 4月   4 19:01 .config

参考mini2440.config文件作为我们的默认.config文件。改好之后再

[luminqi@localhost linux-3.0]$ make menuconfig

fl2440内核移植过程Linux-3.0

fl2440内核移植过程Linux-3.0

fl2440内核移植过程Linux-3.0

打开文本窗口来选定即将要编译的模块,保存后会将里面的信息保存到同时生成的.config配置文件中。

另外:make menuconfig时出来的文本窗口中的信息是通过读取在内核源代码目录下的Kconfig文件来配置的。根据Makefile文件来编译,而Makefile文件中的变量则通过.config来进行赋值操作。仅仅在Kconfig中添加选项。


4.修改MACHINE ID设备编号
因为我u-boot中设置fl2440使用的machine id为1999,所以内核中设置fl2440的
machine id也要一样

[luminqi@localhost linux-3.0]$ vim arch/arm/tools/mach-types

133 @@ -85,7 +85,7 @@
134 bast ARCH_BAST BAST 331
135 h1940 ARCH_H1940 H1940 347
136 enp2611 ARCH_ENP2611 ENP2611 356
137 -s3c2440 ARCH_S3C2440 S3C2440 362
138 +s3c2440 ARCH_S3C2440 S3C2440 1999
139 gumstix ARCH_GUMSTIX GUMSTIX 373
140 omap_h2 MACH_OMAP_H2 OMAP_H2 382
141 e740 MACH_E740 E740 384
142 @@ -356,7 +356,7 @@
143 snapper_9260 MACH_SNAPPER_9260 SNAPPER_9260 1987
144 dsm320 MACH_DSM320 DSM320 1988
145 exeda MACH_EXEDA EXEDA 1994
146 -mini2440 MACH_MINI2440 MINI2440 1999
147 +mini2440 MACH_MINI2440 MINI2440 362
148 colibri300 MACH_COLIBRI300 COLIBRI300 2000
149 linkstation_ls_hgl MACH_LINKSTATION_LS_HGL LINKSTATION_LS_HGL 2005
150 cpuat9g20 MACH_CPUAT9G20 CPUAT9G20 2031


配置就绪之后make ,生成

linux-s3c2440.bin的可执行二进制文件。

5.对nandflash进行分区

[luminqi@localhost linux-3.0]$ vim arch/arm/plat-s3c24xx/common-smdk.c

 

71 @@ -110,44 +110,29 @@
72
73 static struct mtd_partition smdk_default_nand_part[] = {
74 [0] = {
75 - .name = "Boot Agent",
76 - .size = SZ_16K,
77 + .name = "mtdblock0 uboot 1MB",
78 + .size = SZ_1M*1,
79 .offset = 0,
80 },
81 [1] = {
82 - .name = "S3C2410 flash partition 1",
83 - .offset = 0,
84 - .size = SZ_2M,
85 + .name = "mtdblock1 kernel 15MB",
86 + .offset = SZ_1M*1,
87 + .size = SZ_1M*15,
88 },
89 [2] = {
90 - .name = "S3C2410 flash partition 2",
91 - .offset = SZ_4M,
92 - .size = SZ_4M,
93 + .name = "mtdblock2 rootfs 40MB",
94 + .offset = SZ_1M*16,
95 + .size = SZ_1M*40,
96 },
97 [3] = {
98 - .name = "S3C2410 flash partition 3",
99 - .offset = SZ_8M,
100 - .size = SZ_2M,
101 + .name = "mtdblock3 apps 100MB",
102 + .offset = SZ_1M*56,
103 + .size = SZ_1M*100,
104 },
105 [4] = {
106 - .name = "S3C2410 flash partition 4",
107 - .offset = SZ_1M * 10,
108 - .size = SZ_4M,
109 - },
110 - [5] = {
111 - .name = "S3C2410 flash partition 5",
112 - .offset = SZ_1M * 14,
113 - .size = SZ_1M * 10,
114 - },
115 - [6] = {
116 - .name = "S3C2410 flash partition 6",
117 - .offset = SZ_1M * 24,
118 - .size = SZ_1M * 24,
119 - },
120 - [7] = {
121 - .name = "S3C2410 flash partition 7",
122 - .offset = SZ_1M * 48,
123 - .size = MTDPART_SIZ_FULL,
124 + .name = "mtdblock4 data 100MB",
125 + .offset = SZ_1M*156,
126 + .size = SZ_1M*100,
127 }
128 };

在这里我的分区是

uboot:1M        0-0x100000(0x100000)            0(开始)-0x60000(大小)          kernel:15M     0x100000-0x1000000(0xf00000)       0x100000-0x800000 rootfs:40M     0x1000000-0x3800000(0x2800000)     0x1000000- (最大可写0x2800000,根据文件系统大小调整) apps:100M       0x3800000-0x9c00000(0x6400000)     0x3800000-
data:100M       0x9c00000-0x10000000(0x6400000)    0x9c00000-

此时能编译成功,但是生成的linux-s3c2440.bin文件依旧不能在板子上跑起来。

因为内核启动时首先挂载的是根文件系统,我们还没有做根文件系统给予内核支持,系统会出错而退出启动。

3. 添加根文件系统支持
1、根文件系统简介
文件系统是对一个存储设备上的数据和元数据进行组织的机制。这种机制有利于用户和操作系统的交互。而根文件系统则是所有文件系统的根,我理解的是所有文件系统都是由根文件系统扩展开来的。而若是没有根文件系统则谈不上其他的文件系统。根文件系统它包含系统引导以及其他文件系统所能挂载的必要文件。

什么是根文件系统?首先是一种文件系统,但是相对于普通的文件系统,它的特殊之处在于,它是内核启动时所mount的第一个文件系统。而Linux又支持多种文件系统,包括ext2、ext3、vfat、ntfs、iso9660、jffs、romfs和nfs等,为了对各类文件系统 进行统一管理,Linux引入了虚拟文件系统VFS(Virtual File System),为各类文件系统提供一个统一的操作界面和应用编程接口。Linux启动时,第一个必须挂载的是根文件系统;若系统不能从指定设备上挂载根文件系统,则系统会出错而退出启动。之后可以自动或手动挂载其他的文件系统。因此,一个系统中可以同时存在不同的文件系统。不同的文件系统类型有不同的特点,因而根据存储设备的硬件特性、系统需求等有不同的应用场合。在嵌入式Linux应用中,主要的存储设备为 RAM(DRAM, SDRAM)和ROM(常采用FLASH存储器),常用的基于存储设备的文件系统类型包括:jffs2, yaffs, cramfs, romfs, ramdisk, ramfs/tmpfs等。

2、根文件系统支持
本文主要写内核的移植与启动,所以选择了制作很简单的initramfs文件系统作为根文件系统,它能伴随内核编译时同时与内核生成一个镜像而能与之一起启动。


[luminqi@localhost linux-3.0]$ make menuconfig

fl2440内核移植过程Linux-3.0


fl2440内核移植过程Linux-3.0


fl2440内核移植过程Linux-3.0

这里的路径是你根文件系统所在的路径,视情况而定

在选择保存后即可连接开发板。重新编译内核后下载到板子上便可以启动了!


添加dm9000网卡的支持

vim arch/arm/mach-s3c2440/mach-smdk2440.c

 4 @@ -22,6 +22,7 @@
5 #include <linux/serial_core.h>
6 #include <linux/platform_device.h>
7 #include <linux/io.h>
8 +#include <linux/dm9000.h>
9
10 #include <asm/mach/arch.h>
11 #include <asm/mach/map.h>
12 @@ -47,6 +48,40 @@
13
14 #include <plat/common-smdk.h>
15
16 +#define DM9000_BASE (S3C2410_CS4 + 0x300)
17 +static struct resource s3c_dm9000_resource[] = {
18 + [0] = {
19 + .start = DM9000_BASE,
20 + .end = DM9000_BASE + 3,
21 + .flags = IORESOURCE_MEM
22 + },
23 + [1] = {
24 + .start = DM9000_BASE + 4,
25 + .end = DM9000_BASE + 7,
26 + .flags = IORESOURCE_MEM
27 + },
28 + [2] = {
29 + .start = IRQ_EINT7,
30 + .end = IRQ_EINT7,
31 + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
32 + }
33 +};
34 +/*
35 + * * The DM9000 has no eeprom, and it's MAC address is set by
36 + * * the bootloader before starting the kernel.
37 + * */
38 +static struct dm9000_plat_data s3c_dm9000_pdata = {
39 + .flags = (DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM),
40 +};
41 +static struct platform_device s3c_device_dm9000 = {
42 + .name = "dm9000",
43 + .id = -1,
44 + .num_resources = ARRAY_SIZE(s3c_dm9000_resource),
45 + .resource = s3c_dm9000_resource,
46 + .dev = {
47 + .platform_data = &s3c_dm9000_pdata,
48 + },
49 +};
50 static struct map_desc smdk2440_iodesc[] __initdata = {
51 /* ISA IO Space map (memory space selected by A24) */
53 @@ -155,12 +190,13 @@
54 &s3c_device_wdt,
55 &s3c_device_i2c0,
56 &s3c_device_iis,
57 + &s3c_device_dm9000,
58 };


重新make之后,我们的内核文件就支持dm9000网卡了,在开发板上跑起来后,就能够ping 192.168.1.2(电脑有线IP



开发板上的操作:

在u-boot启动内核的时候需用通过bootargs和bootcmd给内核传递参数进入 u-boot 时对这两个环境变量进行修改,修改如下:

[fl2440~]# set bootargs 'console=ttyS0,115200 mem=64M rw loglevel=7'

[fl2440~]set bootcmd 'nand read 30008000 100000 800000; bootm 30008000'

[fl2440~]set bkr 'tftp 30008000 linuxrom-s3c2440.bin;nand erase 100000 f00000;nandwrite 30008000 100000 800000'

[fl2440~]save

[fl2440~]# run bkr  //将内核加载到内存,然后清除nandflash,再将内存写入nandflash,对应上面的设置set bkr

[fl2440~]# boot      //读取内核,并启动内核,对应上面的设置set bootcmd

[fl2440~]# reboot   //重启

//nand erase 100000 f00000就是从0x100000处开始擦除0xf00000(大小)的存储空间,对于nandflash,每次都应该先清除再写入,为什么要清除这个大小呢?这和上面的分区有关,我上面给内核这一块分配了15M,这里0x1000000减0x100000等于0xf00000,0xf00000就是15M,不理解的可以百度十六进制和内存存储的转换,一般清除都是整一块的清除,这取决于你在内核里的分区情况.

//nand write 30008000 100000 800000就是将内核(此时在内存中,内存起始地址为0x30008000)写入nandflash中,起始地址为0x100000,800000指的是要写入的大小(这个只要大于或等于内核大小即可).


这样就完成了内核移植,内核跑起来首先要做好根文件系统,开发板进入u-boot时将选了initramfs文件系统的内核写入nandflash

内核通过u-boot引导启动