在JZ2440上移植设备树—下:内核和设备树移植
本文参考了http://www.cnblogs.com/pengdonglin137/p/6241895.html及韦老师的内核移植视频
2、内核移植
在www.kernel.org上下载源码,我这里选取的是linux-4.15.10版本。
解压后,文件名重命名为linux-4.15.10-jz2440。 cd进入
既然要使用设备树,我们先看内核中是否已有支持2440的设备树文件。
cd arch/arm/boot/dts
ls
发现并没有支持2440的设备数,最接近的只有2416的设备数;
find -name “*defconfig” 发现在
arch/arm/configs 下有
mini2440_defconfig和s3c2410_defconfig两个接近的配置文件。
2.1 内核编译
2.1.1 添加设备树文件
我的思路是内核配置文件选取s3c2410_defconfig,
设备树复制s3c2416.dtsi为s3c2440.dtsi
复制s3c2416-pinctrl.dtsi为s3c2440-pinctrl.dtsi
复制s3c2416-smdk2416.dts为s3c2440-jz2440.dts
后面遇到问题,具体分析和修改。
介紹一下上面的几个设备树文件:
skeleton.dtsi 存放的是一個設備樹必備的一些基本屬性
s3c24xx.dtsi 中存放的是整個s3c24xx系列SoC公共的一些屬性,如中斷控制器、串口、看門狗、RTC、I2C控制器等等
s3c2440-pinctrl.dtsi 存放的是s3c2440這款SoC中GPIO控制器、外部中斷控制器、引腳複用等信息的配置
s3c2440.dtsi 存放的是s3c2440這個SoC跟其他s3c24xx系列不同的一些硬件信息,如clock控制器、串口等等
s3c2440-jz2440.dts 存放的是jz2440的硬件信息
設備樹這樣一層層包含的好處是: 在同名節點中,後出現的屬性會覆蓋前面出現的同名屬性,不同的屬性將來會合併到所隸屬的同名的節點下面。
先修改设备树的Makefile
vim arch/arm/boot/dts/Makefile
这样make dtbs的时候就会编译s3c2440-jz2440.dtb
2.1.2 添加jz2440的板子信息
修改Makefile和Kconfig,并添加jz2440的板子信息,使内核在启动时能从设备树文件中解析到的信息匹配到jz2440板子
2.1.2.1 修改arch/arm/mach-s3c24xx/Kconfig
添加如下信息:
这样的话,在make menuconfig的時候,选择这个这个配置。选择了这个配置,CONFIG_CLKSRC_OF/CONFIG_USE_OF/CONFIG_PINCTRL/CONFIG_S3C24XX都会被配置上。
2.1.2.1 修改arch/arm/mach-s3c24xx/Makefile
在menuconfig上选择了MACH_JZ2440后, 在make uImage的时候会定义CONFIG_MACH_JZ2440宏,这样就会编译mach-jz2440-dt.c
2.1.2.1 添加arch/arm/mach-s3c24xx/mach-jz2440-dt.c文件
#include <linux/clocksource.h>
#include <linux/irqchip.h>
#include <linux/serial_s3c.h>
#include <asm/mach/arch.h>
#include <mach/map.h>
#include <plat/cpu.h>
#include <plat/pm.h>
#include "common.h"
static void __init jz2440_dt_map_io(void)
{
s3c24xx_init_io(NULL, 0);
}
static void __init jz2440_dt_machine_init(void)
{
s3c_pm_init();
}
static const char *const jz2440_dt_compat[] __initconst = {
"samsung,s3c2440",
"samsung,jz2440",
NULL
};
DT_MACHINE_START(S3C2440_DT, "Samsung S3C2440 (Flattened Device Tree)")
.dt_compat = jz2440_dt_compat,
.map_io = jz2440_dt_map_io,
.init_irq = irqchip_init,
.init_machine = jz2440_dt_machine_init,
MACHINE_END
如果内核配置make menuconfig中选择支持设备树
make menuconfig --->
Boot options --->
Flattened Device Tree support
那么内核在启动时,不会通过u-boot传入的machid来找到单板文件;而是通过上面的dt_compat数组中的信息和设备树中的compatible进行匹配,以此来找到相应单板文件。设备树中的相关设置如下图:
2.1.3 内核配置make menuconfig
在执行make menuconfig之前先要确定默认的配置文件。前面已有描述,选取s3c2410_defconfig作为默认配置文件,在内核代码主目录下先执行
make ARCH=arm exynos_defconfi
再执行
make ARCH=arm menuconfig
进入配置菜单
ps:前面讲过 配置内核支持设备树,配置内核支持JZ2440单板文件,这里不再重复。
2.1.3.1 配置打开内核调试
在啓動kernel的時候最煩人的是,uboot打印出”Starting kernel …”後,整個系統就沒有任何動靜了,此時,就需要打開內核早期的調試log,方法如下:
爲了能夠儘量看到更多內核啓動早期的log,一定要在內核配置文件中把內核早期的log配置打開:
Kernel hacking --->
[*] Kernel low-level debugging functions (read help!)
Kernel low-level debugging port (Use Samsung S3C UART 0 for low-level debug) --->
[*] Early printk
除了上面的配置,還必須在bootargs中添加一個earlyprintk字符串,否則這些log還是打印不出來,此外,建議再在bootargs中添加一個ignore_loglevel參數,防止有些模塊的log由於loglevel的問題無法輸出log
具体的bootargs参数会在后面给出。
2.1.3.2 配置内核支持DM9000网卡
已经确定JZ2440上有DM90000,我们在内核配置时,先把相应配置选上。
make ARCH=arm menuconfig
[*] Networking support --->
Networking options --->
<*> Packet socket
<*>Unix domain sockets
[*] TCP/IP networking
[*] IP: kernel level autoconfiguration
Device Drivers --->
[*] Network device support --->
[*] Ethernet driver support (NEW) --->
<*> DM9000 support
2.1.3.3 配置内核支持根文件系统类型
如果内核还没有移植好网卡和存储设备驱动,可以先尝试通过内存虚拟文件系统ramdisk先把内核调通,再去支持其他的文件系统类型。关于 ramdisk 的使用可以参考https://blog.csdn.net/u014213012/article/details/51582826
我在这里尝试使用nfs网络文件系统,相应内核配置如下:
File systems --->
[*] Network File Systems (NEW) --->
<*> NFS client support
[*] NFS client support for NFS version 3
[*] NFS client support for the NFSv3 ACL protocol extension
[*] Root file system on NFS
bootargs启动参数设置如下:
bootargs=noinitrd root=/dev/nfs nfsroot=192.168.8.3:/nfs/rootfs rw
clk_ignore_unused console=ttySAC0,115200 init=/linuxrc
ip=192.168.8.4:192.168.8.3:192.168.8.1:255.255.255.0::eth0:off
ignore_loglevel earlyprintk
这里我们通过bootargs告知内核根文件系统为nfs网络文件系统,并详细的设置了ip,服务器ip,网关等网络参数信息,方便内核启动时直接通过这些参数去挂载nfs网络文件系统。这里我们直接采用韦老师制作好的文件系统—fs_mini_mdev_new.tar.bz2
将其解压到linux主机/nfs/rootfs目录下。
ps:
关于根文件系统的制作可以参考韦老师视频、华清相关课程和网络相关资料
关于uboot的环境变量及bootargs设置请参考:
https://blog.csdn.net/dzw19911024/article/details/52334254
2.1.4 内核编译
配置好内核.config文件后,在内核主目录下
make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-
编译生成zImage。其中的gcc版本为gcc-4.6.4,其安装和添加PATH方法不再赘述。
make dtbs ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-
编译设备树文件,把前面配置过的arch/arm/boot/dts里的dts文件编译成dtb文件。
cd arch/arm/boot 进入zImage目录,使用mkimage 工具将zImage制作成uImage
mkimage -A arm -O linux -T kernel -C none -a 0x31000000 -e 0x31000040 -n "jz2440" -d zImage uImage
我们先将生成的uImage文件和s3c2440-jz2440.dtb文件放入/tftpboot目录,使用tftp服务,在uboot启动时使用tftp服务将内核和设备树从tftp服务器中加载到内存,然后bootm。具体的bootcmd参数如下:
bootcmd=tftp 31000000 uImage; tftp 32000000 s3c2440-jz2440.dtb; bootm 31000000 - 32000000
先不管根文件系统和bootargs,直接启动板子,看内核启动运行情况。
结果发现,内核和设备树加载到内存后,内核无法正常运行;后续就是设备树的修改工作了;
ps:mkimage 的使用方法参考
https://blog.csdn.net/qq_29350001/article/details/51490415
2.2 修改设备树
因为前面配置了earlyprintk,串口正常情况下一定会有输出,这样我们就可以根据输出的信息,分析和查找原因,对症下药进行修改调整,并最终成功挂接到根文件系统,完成移植。
2.2.1 修改设备树compatible
前面提到过修改s3c2440-jz2440.dts设备树的compatible,同时也要修改s3c2440.dtsi中的compatible,这里不再重复。
2.2.2 修改串口部分
首先,我们发现串口到最后输出乱码:
根据此信息我们大概猜测为串口有两个问题,1、串口初始化较多,可能是多个串口之间产生了干扰;2、由于我们复制了2416的设备树文件,其中的信息还没改成2440。
打开s3c2440-jz2440.dts文件,将串口1至串口3的设备树信息先屏蔽掉;
打开s3c2440.dtsi文件,将串口属性改为2440,如下:
2.2.3 DM9000设备树配置
在s3c2440-jz2440.dts中添加
srom-cs4@20000000 {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
reg = <0x20000000 0x8000000>;
ranges;
ethernet@18000000 {
compatible = "davicom,dm9000";
reg = <0x20000000 0x2 0x20000004 0x2>;
interrupt-parent = <&gpf>;
interrupts = <7 4>;
local-mac<