11. 移植linux-4.15内核到JZ2440
11. 1 实验环境
开发板: JZ2440开发板
u-boot : u-boot-2016.03 编译器: arm-linux-gcc-4.3.2
busybox: busybox-1.20.0 编译器: arm-linux-gcc-4.3.2
linux: linux-4.15 编译器: arm-linux-gnueabi-gcc-4.9.4
注:对于为什么使用不同的两个不同的编译器,因为使用uboot使用 arm-linux-gnueabi-gcc-4.9.4 编译出来的u-boot.bin烧写到开发板不能启动,arm-linux-gcc-4.3.2 编译linux-4.15会出错, arm-linux-gnueabi-gcc-4.9.4 编译出来的busybox在内核启动时出现错误:Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b。
11.2 获取源码
(1) busybox-1.20.0源码的下载地址:https://busybox.net/downloads/
(2) linux-4.15 源码的下载地址:https://mirrors.edge.kernel.org/pub/linux/kernel/v4.x/linux-4.15.tar.gz
11.3 linux-4.15内核移植
(1) 把从官网下载的linux-4.15.tar.gz内核源码拷贝到Ubuntu服务器解压内核:
tar xzf linux-4.15.tar.gz
(2) 进入linux-4.15目录,并修改顶层目录Makefile指定CPU架构和交叉编译器,把
ARCH ?= $(SUBARCH)
CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%)
修改为:
ARCH ?= arm
CROSS_COMPILE ?= arm-linux-gnueabi-
(3) 配置linux-4.15内核,编译:
make s3c2410_defconfig
make menuconfig
make uImage -j4
注:make menuconfig 是需要选择使用EABI接口,依次选择:
Kernel Features —>
[*] Use the ARM EABI to compile the kernel
如下图所示:
编译之后把uImage烧写到开发板,启动内核,移植卡在 Starting kernel …
(4) 根据之前移植linux-3.4.2的经验,应该是串口波特率的问题,需要修改晶振频率:把arch/arm/mach-s3c24xx/mach-smdk2440.c的167行:
s3c24xx_init_clocks(16934400);
修改为:
s3c2440_init_clocks(12000000);
同时需要修改uboot的环境变量:(设置ID,修改启动参数)
setenv machid 16a // smdk2440 mach-smdk2440.c
setenv bootargs console=ttySAC0,115200 root=dev/mtdblock3
(5) 修改mtd 分区:在arch/arm/mach-s3c24xx/common-smdk.c有如下代码:
/* NAND parititon from 2.4.18-swl5 */
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 = MTDPART_SIZ_FULL,
}
};
修改为:
/* NAND parititon from 2.4.18-swl5 */
static struct mtd_partition smdk_default_nand_part[] = {
[0] = {
.name = "bootloader",
.size = SZ_512K,
.offset = 0,
},
[1] = {
.name = "params",
.offset = MTDPART_OFS_APPEND,
.size = SZ_256K,
},
[2] = {
.name = "kernel",
.offset = MTDPART_OFS_APPEND,
.size = SZ_4M,
},
[3] = {
.name = "rootfs",
.offset = MTDPART_OFS_APPEND,
.size = MTDPART_SIZ_FULL,
},
};
上面的mtd分区要跟uboot的mtdparts相对应,由于新的kernel比较大,原先的2M不够,故这里修改为4M;同时也要把uboot的mtd分区的kernel分区修改为4M (在include/configs/jz2440.h里修改)
(6) 重新编译内核,烧写内核进行测试:
a. 设置uboot启动参数:
setenv bootargs console=ttySAC0,115200 root=/dev/mtdblock3 rootfstype=jffs2
b.首先我们把之前制作好的jffs文件系统烧写到开发板NAND Flash 的 rootfs分区,命令如下:
nfs 30000000 192.168.0.101:/home/book/works/first_fs/rootfs.jffs2 //使用nfs下载rootfs.jffs2文件系统到30000000地址
nand erase.part rootfs //擦除rootfs分区
nand write.jffs2 30000000 rootfs $filesize //使用nand write.jffs2将30000000地址的大小为filesize的文件写到rootfs分区
c.烧写内核测试
nfs 32000000 192.168.0.101:/home/book/works/first_fs/uImage
bootm 32000000
内核启动成功,如下图所示,内核成功挂载了文件系统。
11.4 制作根文件系统
(1) 解压 busybox 源码:
tar xjf busybox-1.20.0.tar.bz2
(2) 配置 busybox,设置交叉编译器:
make menuconfig
出现下面的界面:
设置交叉编译器:
选择:
Busybox Settings —>
Build Options —>
Cross Compiler prefix (NEW)
然后会出现可以输入的横条,在里面输入我们的编译器的前缀:
配置好后,退出保存保存配置。
然后直接编译:make
编译完成后,把它安装到 rootfs ,新建目录:
mkdir rootfs
切换到busybox目录下进行安装:
make install CONFIG_PREFIX=../rootfs
安装完成后,rootfs目录下的文件如下图所示:
第一步已经完成,busybox已经安装好,下一步是安装库。
(3) 安装库
查看工具链的路径:echo $PATH
可知工具链的路径是:/work/tools/arm-linux-gcc-4.3.2/bin
进入/work/tools/arm-linux-gcc-4.3.2/
目录:cd /work/tools/arm-linux-gcc-4.3.2/
输入:find -name lib
找到很多库如下:
用到的库只有这两个:
./arm-none-linux-gnueabi/libc/armv4t/usr/lib
./arm-none-linux-gnueabi/libc/armv4t/lib
① 把/work/tools/arm-linux-gcc-4.3.2/arm-none-linux-gnueabi/libc/armv4t/lib
目录下的所有.so
文件拷贝到rootfs/lib目录下:(注:rootfs目录下的lib目录需要新建)
cp /work/tools/arm-linux-gcc-4.3.2/arm-none-linux-gnueabi/libc/armv4t/lib/*so* /home/book/works/busybox/rootfs/lib -d (-d代表原来是链接文件,拷贝过来之后还是链接文件)
② 把/work/tools/arm-linux-gcc-4.3.2/arm-none-linux-gnueabi/libc/armv4t/usr/lib
目录下的所有.so
文件拷贝到rootfs/usr/lib目录:(注:usr 下的lib目录需要新建)
cp /work/tools/arm-linux-gcc-4.3.2/arm-none-linux-gnueabi/libc/armv4t/usr/lib/*so* /home/book/works/busybox/rootfs/usr/lib -d
(4) 构造etc目录
① 创建etc/inittab文件:在rootfs目录下创建etc目录,在etc目录下创建inittab文件,内容如下:
# /etc/inittab
::sysinit:/etc/init.d/rcS
console::askfirst:-/bin/sh
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
② 创建etc/init.d/rcS文件
#!/bin/sh
ifconfig eth0 192.168.0.200
mount -a
mkdir /dev/pts
mount -t devpts devpts /dev/pts
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s
同时为该文件添加可执行权限:chmod +x etc/init.d/rcS
③ 创建etc/fstab文件:
# device mount-point type options dump fsck order
proc /proc proc defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
sysfs /sys sysfs defaults 0 0
tmpfs /dev tmpfs defaults 0 0
(5) 构造dev目录
mdev是通过init进程来启动的,在使用mdev构造/dev目录之前,init进程至少要用到的设备文件为/dev/console和/dev/null,所以要建立这两个文件:
mkdir dev
cd dev
sudo mknod console c 5 1
sudo mknod null c 1 3
(6) 构建其他目录
mkdir proc mnt sys root tmp
(7) 制作jffs2映像文件:进入rootfs所在的目录,输入以下命令:
mkfs.jffs2 -n -s 2048 -e 128KiB -d rootfs -o rootfs.jffs2
上面-n 表示不要在每个擦除块上都加上清除标志,-s 2048 表示我们的NAND Flash的一页的大小为2048字节,-e 128KiB 表示一个擦除快大小为128KiB ,-d 表示根文件系统的目录,-o表示输出的文件。
(8) 测试制作好的文件系统
nfs 30000000 192.168.0.101:/home/book/works/busybox/rootfs.jffs2
nand erase.part rootfs
nand write.jffs2 30000000 rootfs $filesize
setenv bootargs console=ttySAC0,115200 root=/dev/mtdblock3 rootfstype=jffs2
nfs 32000000 192.168.0.101:/home/book/works/first_fs/uImage
bootm 32000000
启动内核后,打印信息如下,可见整个linux系统跑起来了。
11.5 修改内核代码支持YAFFS文件系统
(1) 获取yaffs源码
获取源码yaffs源码的方式有很多种,这里我是直接从Jz2440开发板光盘资料中获取的yaffs源码。把它拷贝到Ubuntu服务器下并解压。
(2) 给linux内核打补丁
进入到yaffs2源码目录,使用下面的命令进行打补丁:
./patch-ker.sh c m /home/book/works/linux-4.15 //后面这个是我的linux内核源码目录
打完补丁后,就会在内核的fs/yaffs2目录下加入了yaffs的源码
(3) 配置内核支持YAFFS
在linux源码顶层目录下输入:
make menuconfig
依次选择:
File systems --->
Miscellaneous filesystems --->
<*> yaffs2 file system support
然后保存配置,重新编译内核:
make uImage -j4
编译成功。
(4) 制作yaffs2文件系统系统映像
进入rootfs所在的目录,输入以下命令:
mkyaffs2image rootfs rootfs.yaffs2
(5) 测试制作好的文件系统
nfs 30000000 192.168.0.101:/home/book/works/busybox/rootfs.yaffs2
nand erase.part rootfs
nand write.yaffs 30000000 rootfs $filesize //烧写文件系统
setenv bootargs console=ttySAC0,115200 root=/dev/mtdblock3 rootfstype=yaffs2
nfs 32000000 192.168.0.101:/home/book/works/first_fs/uImage
bootm 32000000
如下图所示,yaffs文件系统成功挂载,linux启动成功,整个系统运行正常。
11.6 制作内核补丁
进入内核的顶层目录:
cp .config config_ok
make distclean
/*退出内核目录,重命名*/
mv linux-4.15 linux-4.15_jz2440
tar xzf linux-4.15.tar.gz
diff -urN linux-4.15 linux-4.15_jz2440 > linux-4.15_jz2440.patch
进入linux-4.15顶层目录打补丁:
patch -p1 < ../linux-4.15_jz2440.patch
cp config_ok .config
make uImage