移植Linux 3.4.2内核到JZ2440开发板(超精讲)

Linux 3.4.2内核移植到JZ2440开发板

0、开发环境

  • 虚拟机:VMware workstation 16 pro
  • 宿主机操作系统:Ubuntu 16.04
  • 开发板:JZ2440
  • 移植内核版本:Linux 3.4.2

1、内核下载及内核启动流程简述

1.1 点击上述链接,找到需要得内核版本(此文使用Linux3.4.2)

  • 点击Linux内核下载地址获取内核源码

  • 获取后放到Linux系统上解压:tar -jxf linux-3.4.2.tar.bz2

    Linux内核有3万多个文件,可以将v参数去掉,不显示解压信息。

1.2 内核启动大致流程

  • bootloader
    • 加载内核代码到内存中
    • 设置tag参数
    • 启动内核(R0 = 0, R1 = machid,R2 = tag参数地址)
  • 内核
    • 根据machid判断内核是否支持该机器(支持则启动,不支持则卡死)
    • 解析tag参数
    • 装载驱动(Flash、网卡。。。)
    • 挂载根文件系统
  • 应用程序
    • 运行用户应用程序

2、配置并编译内核

2.1 配置架构和编译工具链

在根目录下的makefile中搜索ARCH,找到并按下图修改两项配置:

image-20210624230540844

2.2 选择默认配置文件

进入arm架构的单板默认配置文件目录(arch/arm/configs/)查看内核支持的单板:

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第1张图片

选择和我们单板最为接近的s3c2410进行编译。

回到根目录,执行命令make s3c2410_defconfig,生成 s3c2410_defconfig默认配置文件.config。该文件中将支持的单板列表如下:

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第2张图片

2.3 编译内核

执行命令make uImage,生成内核镜像文件:

编译过程中的错误:

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第3张图片

  • recipe for target ‘kernel/timeconst.h’ failed

原因:因为在新版本的(Linux) 宿主机上编译老版本的内核版本出现的错误。

解决办法:将kernel/timeconst.pl中第373行的宏判断defined()去掉,去掉后如下:

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第4张图片

  • “mkimage” command not found - U-Boot images will not be built。

image-20210624233216825

原因:Linux主机中制作uImage镜像依赖的一个包没安装。

解决办法:执行sudo apt-get install u-boot-tools命令,安装依赖的包。

再次编译,编译成功。

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第5张图片

3、设置machid(选择机器类型)

3.1 查看uboot中的machid

uboot启动内核的时候,如果环境变量未设置machid 的值,则会使用代码默认的宏定义。代码在文件u-boot-2012.04.01/arch/arm/lib/bootm.c中的函数 boot_jump_linux 中:

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第6张图片

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中:

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第7张图片

再来查找宏定义MACH_TYPE_SMDK2410的值,在文件u-boot-2012.04.01/arch/arm/include/asm/mach-types.h中:

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第8张图片

所以,uboot默认传递的machid的值为193,即0xc1

3.2 查看linux内核中的machid

查询当前Linux内核支持的machid有一种快速简洁的方法:因为uboot启动时会先去寻找环境变量中的值,如果不存在的话才会使用默认值,所以我们先随意设置一个machid的值,当该值不在支持的机器列表中时,在linux启动时就会列出目前所有支持的机器:

  • 先直接在uboot命令行中执行set machid 0xff0(但不要执行saveenv命令,其会将设置的machid保存进params分区中),用以设置一个machid的值。
  • 设置成功后重新下载内核映像,启动内核:

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第9张图片

在列出的支持列表中,可以看到SMDK2440的machid为0x16a

这里有两种设置方法:

① 在uboot中修改赋值给bi_arch_number的宏为16a,然后重新编译,烧写uboot;

② 设置machid为16a,然后使用saveenv命令保存到环境中;

这里使用第二种方法修改machid并保存到环境变量中:

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第10张图片

接着再次尝试启动内核,启动后内核输出乱码:

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第11张图片

在内核源码中找到该machid对应的单板文件为arch\arm\mach-s3c24xx\mach-smdk2440.c文件,在smdk2440_map_io 函数中可以看到晶振设置有问题,JZ2440板载的是12M晶振,所以修改如下:

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第12张图片

重新配置编译内核,下载到开发板中启动,识别出的机器为SMDK2440:

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第13张图片

4、修改内核中的mtd分区

在上一节Linux系统启动之后,打印出的分区表和实际对nand flash的分区表不一致,所以接下来要修改内核中的mtd分区表同uboot中的一致:

0x00000000-0x00040000 : "bootloader"
0x00040000-0x00060000 : "params"
0x00060000-0x00260000 : "kernel"
0x00260000-0x10000000 : "rootfs"

4.1 定位修改代码位置

通过linux启动后,打印出的分区表信息如下:

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第14张图片

所以,内核的根目录下执行grep "\"Boot Agent\"" * -nR搜索“Boot Agent”,结果如图:

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第15张图片

判断在arch/arm/mach-s3c24xx/common-smdk.c:113:处,进入该文件,果然分区表在这里:

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第16张图片

修改为如下的分区表,其中三个宏定义的意思如下:

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第17张图片

  • MTDPART_OFS_APPEND:追加到上一个分区结束地址;
  • MTDPART_SIZ_FULL:剩下的所有空间;

重新编译,下载到开发板的内存中,然后启动内核,可以看到分区表已经被修改成功:

image-20210626152049492

5、内核的裁剪

在前面的移植过程中,内核编译出来有 2414KB,而 Nand Flash 的 mtd 分区中指定了 kernel 分区为 2M=2048KB,所以需要对内核进行裁剪,去除不必要的内容。

5.1、选择s3c2410进行默认配置后,进入图形配置窗口

make s3c2410_defconfig
make menuconfig

5.2、裁剪支持的机器

  • 依次进入System Type -> SAMSUNG S3C24XX SoCs Support ,只需按下图勾选上*** S3C24XX SoCs *** 里的SAMSUNG S3C2440 和*** S3C2440 Boards ***里的SMDK2440SMDK2440 with S3C2440 CPU module选项,其余全部不选:

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第18张图片

5.3、裁剪支持的文件系统

  • 进入File systems,去除对Ext2和Ext3文件系统的支持:

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第19张图片

  • 进入 File systems -> CD-ROM/DVD Filesystems,去除对ISO9600 的支持:

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第20张图片

  • 进入 File systems -> DOS/FAT/NT Filesystems,去除对MSDOS和VFAT文件系统的支持:

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第21张图片

  • 进入 File systems -> Miscellaneous filesystems,去除对cramfs、ZLIB压缩型文件系统和ROM文件系统的支持:

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第22张图片

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第23张图片

5.4、裁剪支持的设备驱动

  • 进入 Device Drivers -> SCSI device support,去除对SCSI设备和RAID传输类设备的支持:

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第24张图片

  • 进入 Device Drivers -> Input device support,去除对psaux、鼠标、键盘、游戏棒的支持:

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第25张图片

  • 进入 Device Drivers -> Network device support -> Ethernet driver support(只保留DM9000):

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第26张图片

  • 进入 Device Drivers -> Input device support -> Touchscreens,选上S3C2410 touchscreen input driver:

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第27张图片

  • 进入 Device Drivers -> Sound card support -> Advanced Linux Sound Architecture,去除USB声卡设备:

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第28张图片

  • 进入Device Drivers -> Multifunction device drivers,去除Silicon Motion SM501的支持:

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第29张图片

  • 进入Device Drivers -> USB support,去除对USB 文件系统、OHCI HCD、通用存储设备共享表(the shared table of common storage devices)、USB串口转换(USB serial converter)的支持:

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第30张图片

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第31张图片

  • 进入Device Drivers -> MMC/SD/SDIO card support,去除对MMC block device驱动的支持:

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第32张图片

5.5、配置EABI支持

  • 进入Kernel Features ,选择勾选Use the ARM EABI to compile the kernelAllow old ABI binaries to run with this kernel (EXPERIMENTAL)

如果内核不支持eabi,在启动时将会提示:Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000004

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第33张图片

6、移植DM9000网卡驱动,支持网络,支持NFS挂载,支持域名解析

6.1、移植DM9000网卡驱动

之前配置使用的SMDK2440开发板,默认不支持DM9000网卡驱动,但是其中的MINI2440开发板支持,所以要将MINI2440中的DM9000驱动移植到SMDK2440中。

进入内核源码目录里面,找到 arch/arm/mach-s3c24xx/目录并进入,找到这两个文件:mach-smdk2440.carch-mini2440.c,并将 mach-mini2440.c 中关于网卡的配置代码,移植到 mach-smdk2440.c 中。

  • 向mach-smdk2440.c文件中添加头文件:#include

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第34张图片

  • 向mach-smdk2440.c文件中移植并修改结构体SMDK2440_dm9k_resource

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第35张图片

  • 移植并修改smdk2440_dm9k_pdata结构体

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第36张图片

  • 添加宏定义MACH_SMDK2440_DM9K_BASE

image-20210626215239068

  • 修改smdk2440_devices结构体

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第37张图片

保持之前的配置不变,重新编译内核!

7、网络测试

7.1、局域网测试

  • 设置网卡ip地址,启动网络连接
ifconfig eth0 192.168.1.50	//设置板子的ip地址
ifconfig eth0 up
  • ping测试
ping 192.168.1.100	//ping宿主机

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第38张图片

  • 设置开机启动后自动配置ip地址

在开发板上使用vi编辑器编辑etc/init.d/rcS文件,添加一条配置命令即可:

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第39张图片

重启测试:

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第40张图片

7.2、外网测试

  • 配置网关:
route add default gw 192.168.1.1 dev eth0
  • 如果想开机后自动设置网关ip,仅需在开发板上使用vi编辑器编辑etc/init.d/rcS文件,添加一条配置命令即可:

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第41张图片

  • 重启之后ping外网测试:

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第42张图片

7.3、域名解析测试

  • 配置DNS域名解析服务器,在 /etc 目录下新建一个文件resolv.conf,然后编辑添加以下内容:
nameserver 114.114.114.114

进行ping域名测试,成功:

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第43张图片

8、挂接NFS文件系统

NFS是Network File System,网络文件系统,可以通过网络让不同机器、不同系统之间实现文件共享。通过NFS ,可以访问远程共享目录,就和访问本地磁盘一样。在嵌入式Linux开发中常用于开发板运行目标机上的程序。

8.1、linux主机建立NFS服务器端

  • 安装NFS服务器
sudo apt-get install nfs-kernel-server
  • 添加NFS共享目录

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
  • 打开、编辑配置文件/etc/exports,在末尾添加指定NFS共享目录的语句
/home/leon/nfs_root/first_fs *(rw,sync,no_root_squash)
  • 启动/重启 NFS服务
sudo /etc/init.d/nfs-kernel-server start
sudo /etc/init.d/nfs-kernel-server restart

注:NFS服务在系统启动时会自动启动。

image-20210626221012952

8.2 Linux主机建立NFS客户端自测

  • 安装NFS客户端
sudo apt-get install nfs-common
  • 挂载NFS共享目录到/mnt
sudo mount -t nfs -o nolock localhost:/home/leon/nfs_root/first_fs /mnt

提示错误:

image-20210626222759621

**问题原因:**被拒绝的原因是因为使用了非法端口。因为如果端口号大于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 选项:

移植Linux 3.4.2内核到JZ2440开发板(超精讲)_第44张图片

  • 在NFS服务器端的共享文件夹/home/leon/nfs_root/first_fs新建测试文件test
cd /home/leon/nfs_root/first_fs
touch test
  • 进入客户端挂载的文件夹/mnt查看是否有test文件,并尝试写入
cd /mnt
ls

echo "leon" >> test

8.3 开发板开机自动挂载NFS网络文件系统

  • 重启开发板,进入uboot命令行,修改启动参数,保存后,重启:
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
    

你可能感兴趣的:(嵌入式开发,内核移植,移植DM9000到内核,挂接NFS文件系统,JZ2440内核移植,linux3.4.2内核移植)