点击Linux内核下载地址获取内核源码
获取后放到Linux系统上解压:tar -jxf linux-3.4.2.tar.bz2
Linux内核有3万多个文件,可以将v参数去掉,不显示解压信息。
在根目录下的makefile中搜索ARCH,找到并按下图修改两项配置:
进入arm架构的单板默认配置文件目录(arch/arm/configs/)查看内核支持的单板:
选择和我们单板最为接近的s3c2410进行编译。
回到根目录,执行命令make s3c2410_defconfig
,生成 s3c2410_defconfig
默认配置文件.config
。该文件中将支持的单板列表如下:
执行命令make uImage
,生成内核镜像文件:
编译过程中的错误:
原因:因为在新版本的(Linux) 宿主机上编译老版本的内核版本出现的错误。
解决办法:将kernel/timeconst.pl
中第373行的宏判断defined()
去掉,去掉后如下:
原因:Linux主机中制作uImage镜像依赖的一个包没安装。
解决办法:执行sudo apt-get install u-boot-tools
命令,安装依赖的包。
再次编译,编译成功。
uboot启动内核的时候,如果环境变量未设置machid 的值,则会使用代码默认的宏定义。代码在文件u-boot-2012.04.01/arch/arm/lib/bootm.c
中的函数 boot_jump_linux 中:
uboot代码中默认的machid值为 gd->bd->bi_arch_number,全局搜索bi_arch_number(grep "bi_arch_number" * -nR
),在文件u-boot-2012.04.01/board/samsung/smdk2440/smdk2440.c
中:
再来查找宏定义MACH_TYPE_SMDK2410的值,在文件u-boot-2012.04.01/arch/arm/include/asm/mach-types.h
中:
所以,uboot默认传递的machid的值为193,即0xc1。
查询当前Linux内核支持的machid有一种快速简洁的方法:因为uboot启动时会先去寻找环境变量中的值,如果不存在的话才会使用默认值,所以我们先随意设置一个machid的值,当该值不在支持的机器列表中时,在linux启动时就会列出目前所有支持的机器:
set machid 0xff0
(但不要执行saveenv
命令,其会将设置的machid保存进params分区中),用以设置一个machid的值。在列出的支持列表中,可以看到SMDK2440的machid为0x16a。
这里有两种设置方法:
① 在uboot中修改赋值给bi_arch_number的宏为16a,然后重新编译,烧写uboot;
② 设置machid为16a,然后使用saveenv命令保存到环境中;
这里使用第二种方法修改machid并保存到环境变量中:
接着再次尝试启动内核,启动后内核输出乱码:
在内核源码中找到该machid对应的单板文件为arch\arm\mach-s3c24xx\mach-smdk2440.c
文件,在smdk2440_map_io 函数中可以看到晶振设置有问题,JZ2440板载的是12M晶振,所以修改如下:
重新配置编译内核,下载到开发板中启动,识别出的机器为SMDK2440:
在上一节Linux系统启动之后,打印出的分区表和实际对nand flash的分区表不一致,所以接下来要修改内核中的mtd分区表同uboot中的一致:
0x00000000-0x00040000 : "bootloader"
0x00040000-0x00060000 : "params"
0x00060000-0x00260000 : "kernel"
0x00260000-0x10000000 : "rootfs"
通过linux启动后,打印出的分区表信息如下:
所以,内核的根目录下执行grep "\"Boot Agent\"" * -nR
搜索“Boot Agent”,结果如图:
判断在arch/arm/mach-s3c24xx/common-smdk.c:113:
处,进入该文件,果然分区表在这里:
修改为如下的分区表,其中三个宏定义的意思如下:
MTDPART_OFS_APPEND
:追加到上一个分区结束地址;MTDPART_SIZ_FULL
:剩下的所有空间;重新编译,下载到开发板的内存中,然后启动内核,可以看到分区表已经被修改成功:
在前面的移植过程中,内核编译出来有 2414KB,而 Nand Flash 的 mtd 分区中指定了 kernel 分区为 2M=2048KB,所以需要对内核进行裁剪,去除不必要的内容。
make s3c2410_defconfig
make menuconfig
Use the ARM EABI to compile the kernel
和Allow old ABI binaries to run with this kernel (EXPERIMENTAL)
。如果内核不支持eabi,在启动时将会提示:
Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000004
。
之前配置使用的SMDK2440开发板,默认不支持DM9000网卡驱动,但是其中的MINI2440开发板支持,所以要将MINI2440中的DM9000驱动移植到SMDK2440中。
进入内核源码目录里面,找到 arch/arm/mach-s3c24xx/
目录并进入,找到这两个文件:mach-smdk2440.c
和arch-mini2440.c
,并将 mach-mini2440.c 中关于网卡的配置代码,移植到 mach-smdk2440.c 中。
#include
SMDK2440_dm9k_resource
保持之前的配置不变,重新编译内核!
ifconfig eth0 192.168.1.50 //设置板子的ip地址
ifconfig eth0 up
ping 192.168.1.100 //ping宿主机
在开发板上使用vi编辑器编辑etc/init.d/rcS文件,添加一条配置命令即可:
重启测试:
route add default gw 192.168.1.1 dev eth0
resolv.conf
,然后编辑添加以下内容:nameserver 114.114.114.114
进行ping域名测试,成功:
NFS是Network File System,网络文件系统,可以通过网络让不同机器、不同系统之间实现文件共享。通过NFS ,可以访问远程共享目录,就和访问本地磁盘一样。在嵌入式Linux开发中常用于开发板运行目标机上的程序。
sudo apt-get install nfs-kernel-server
NFS共享目录:/home/leon/nfs_root/first_fs
其中,first_fs目录是一个最小文件系统,便于以后系统启动后直接通过NFS挂接,方便以后宿主机和开发板直接共享目录。
sudo mkdir /home/leon/nfs_root/first_fs
sudo chmod -R 777 /home/leon/nfs_root/first_fs
sudo chown -R nobody /home/leon/nfs_root/first_fs
/home/leon/nfs_root/first_fs *(rw,sync,no_root_squash)
sudo /etc/init.d/nfs-kernel-server start
sudo /etc/init.d/nfs-kernel-server restart
注:NFS服务在系统启动时会自动启动。
sudo apt-get install nfs-common
sudo mount -t nfs -o nolock localhost:/home/leon/nfs_root/first_fs /mnt
提示错误:
**问题原因:**被拒绝的原因是因为使用了非法端口。因为如果端口号大于1024,则需要将 insecure 选项加入到配置文件(/etc/exports)相关选项中mount客户端才能正常工作。
secure 选项要求mount客户端请求源端口小于1024(然而在使用 NAT 网络地址转换时端口一般总是大于1024的),默认情况下是开启这个选项的,如果要禁止这个选项,则使用 insecure 标识。
详情可参考:NFS挂载问题 mount.nfs: access denied by server while mounting - 一本书的伤痕 - 博客园 (cnblogs.com)
**解决办法:**修改配置文件/etc/exports,加入 insecure 选项:
test
cd /home/leon/nfs_root/first_fs
touch test
/mnt
查看是否有test文件,并尝试写入cd /mnt
ls
echo "leon" >> test
JZ2440 #:setenv bootargs noinitrd root=/dev/nfs nfsroot=192.168.1.100:/home/leon/nfs_root/first_fs init=/linuxrc ip=192.168.1.50:192.168.1.100:192.168.1.1:255.255.255.0::eth0:off console=ttySAC0,115200
JZ2440 #:
JZ2440 #:saveenv
JZ2440 #:boot
192.168.1.100是宿主机ip地址;
192.168.1.50是开发板ip地址;
192.168.1.1是网关;
255.255.255.0是子网掩码;
eth0是网卡名称,可以在系统启动后,命令行输入
ifconfig -a
查看系统当前使用的网卡名称及其ip地址。
查看测试结果
如果设置正确,系统会在启动时直接远程挂接NFS服务器端的最小文件系统first_fs(共享目录),并自动启动sh命令行。
需要注意的是,挂接的最小文件系统必须匹配开发板内核版本,即编译内核和编译busybox的交叉编译器必须是同一个。尤其要注意最小文件系统中的/lib和/usr/lib中的so库文件必须是和交叉编译器使用的库文件一致。例如:我使用的arm-linux-gcc版本是4.3.2,它使用的库文件所在路径为:
/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/lib
/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/usr/lib