本文: 全部参考 袁老师 的配置方法,谢谢袁老师细心指导。
本文续上文之后 https://blog.csdn.net/Eagle6zhen6/article/details/86578377
我们约定:
“$”表示是在主机上执行(Linux系统),
“#”表示在目标板执行 (开发板),
“//”注释
“直接从博客文章中复制代码去运行,有时候,会不行,因为里面隐藏了格式符,我们自己在英文输入法下自己输入就ok啦”
(这里移植的内核是 linux-3.16.62 )
Linux内核源码下载
//下载源码 https://www.kernel.org/
//解压Linux内核源码
tar -xvf linux-3.16.62.tar.xz
//注意解压时只能在 Linux系统下 不能在windows下 (里面有好多的软连接文件)
//cd linux-3.16.62
配置编译工具链和体系架构
//---------------------------------?配置编译源码 (尽量少修改代码,先实现最基本的编译运行,有串口信息输出)
$ vim Makefile /* 指定交叉编译工具链
修改:
ARCH ?= $(SUBARCH)
CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%)
为:
ARCH ?= arm
CROSS_COMPILE ?= arm-none-linux-gnueabi- //交叉编译工具
*/
$ make exynos_defconfig /*导入配置
选最接近我们板子的官方配置(配置列表见 arch/arm/configs/ )
也可采用 $ cp arch/arm/configs/exynos_defconfig .config 的方式导入。
*/
配置内核
$ make menuconfig /*配置内核
System Type --->
(2) S3C UART to use for low-level messages 设置为2,原因是我们使用的串口是com2,和默认配置不一样
如果出现 your display too small 的错, 你把串口窗口放大,就能看到菜单界面了。
如果出现 Install nurse 的错误需安装 apt-get install libncurses5-dev (离线包目录 /var/cache/apt/archives/)
或采用离线包安装dpkg -i libtinfo-dev_5.9-4_i386.deb 后再 dpkg -i libncurses5-dev_5.9-4_i386.deb
*/
$ make uImage /*编译内核
如果报错: /tmp/ccLyO0cX.s:1630: Error: garbage following instruction -- dmb ish
网络后发现是 需新版本的交叉编译工具,网上下一个,
如 gcc-4.6.4.tar.xz 或gcc-linaro-arm-linux-gnueabihf-4.8-2014.04_linux.tar.xz
如果编译过程中提示缺少mkimage工具,需将第二天编译的uboot源码中的tools/mkimage拷贝到ubuntu的/usr/bin目录下
报错 ${MKIMAGE} "$@" 需要 sudo chmod 777 /usr/bin/mkimage
*/
出现错误 在后面添加地址
make uImage LOADADDR=0X40008000
就ok 啦
$ cp arch/arm/boot/uImage /tftpboot
编译设备树
$ make dtbs /* 编译设备树
编译后我们看到支持exynos4412 的board配置有多个,选哪一个呢?
DTC arch/arm/boot/dts/exynos4412-odroidx.dtb
DTC arch/arm/boot/dts/exynos4412-origen.dtb
DTC arch/arm/boot/dts/exynos4412-smdk4412.dtb
DTC arch/arm/boot/dts/exynos4412-tiny4412.dtb
DTC arch/arm/boot/dts/exynos4412-trats2.dtb
结合设备树dts文件,电路图,CPU芯片手册,或ARM官网上这些BOARD的相关资料
最后选exynos4412-origen,它和我们产品最接近。
注:
如果不使用dtb, 运行内核会报错
ERROR: Did not find a cmdline Flattened Device Tree
Could not find a valid device tree
通过错误信息网络搜索,反向知道了为什么要 make dtbs 。因3.14内核使用了设备树,
*/
$ cp arch/arm/boot/dts/exynos4412-origen.dtb /tftpboot/
//---设置开发板u-boot启动参数
# setenv serverip 192.168.9.120 //tftp 服务的ip地址
# setenv ipaddr 192.168.9.9 //板子自己的ip地址
# setenv bootcmd tftp 41000000 uImage\;tftp 42000000 exynos4412-origen.dtb\;bootm 41000000 - 42000000 /*通过tftp下载内核 uImage 设备树exynos4412-origen.dtb 到板子内存,并运行
注意参数别设错了,如下面的这句
setenv bootcmd tftp 41000000 uImage\;tftp 42000000 exynos4412-origen.dtb\;bootm 41000000 – 42000000
*/
# setenv bootargs root=/dev/nfs nfsroot=192.168.9.120:/nfs/rootfs rw console=ttySAC2,115200 init=/linuxrc ip=192.168.9.9 //把启动参数设置为通过nfs 网络挂载根文件系统rootfs
# saveenv
掉电重启板子 //会看到内核信息输出。 但后面有报错,正常 (因为网卡等还没移植,nfs挂载肯定失败)
}
网卡移植
{//---------------------------------?网卡移植(使得NFS挂载成功)
//---配置内核支持: 网络文件系统(NFS) -> 网络协议(tcp/ip等)-> 网卡驱动(dm9000 driver)
$ make menuconfig /*配置如下:
//---配置网络协议支持TCP/IP
[*] Networking support ---> //注意要先输入y 选择该菜单,再按enter键,才能看到下面的选项
Networking options --->
<*> Packet socket
<*> Unix domain sockets
[*] TCP/IP networking
[*] IP: kernel level autoconfiguration
//---配置支持网络文件系统 NFS
File systems --->
[*] Network File Systems --->
<*> NFS client support
<*> NFS client support for NFS version 2
[*] NFS client support for NFS version 3
[*] NFS client support for the NFSv3 ACL protocol extension
[*] Root file system on NFS
//---配置支持dm9000网卡驱动
Device Drivers --->
[*] Network device support --->
[*] Ethernet driver support --->
<*> DM9000 support
*/
//---配置设备硬件信息(设备树)
$ cp arch/arm/boot/dts/exynos4412-origen.dts arch/arm/boot/dts/exynos4412-fs4412.dts
//创建自己的设备树文件(基于origen来修改)
$ vim arch/arm/boot/dts/Makefile /*添加对exynos4412-fs4412.dts的编译
在
exynos4412-origen.dtb \
下添加如下内容
exynos4412-fs4412.dtb \
*/
$ vim arch/arm/boot/dts/exynos4412-fs4412.dts /* 设备树中添加对网卡的支持
在 regulators 前添加下面代码
ethernet@5000000 {
compatible = "davicom,dm9000"; 内核通过该名字来匹配驱动
reg = <0x5000000 0x2 0x5000004 0x2>; 寄存器地址和数据宽度 对应芯片手册 3 Memory Map 的0x0500_0000
interrupt-parent = <&gpx0>; 继承于 中断控制器gpx0
interrupts = <6 4>; 6 对应中断源 DM9000_IRQ -> XEINT6 。4对应 active high level-sensitive
davicom,no-eeprom;
mac-address = [00 0a 2d a6 55 a2];
};
ethernet@5000000 {
37 compatible = "davicom,dm9000";
38 reg = <0x5000000 0x2 0x5000004 0x2>;
39 interrupt-parent = <&gpx0>;
40 interrupts = <6 4>;
41 davicom,no-eeprom;
42 mac-address = [00 0a 2d a6 55 a2];
43 };
*/
(这步没有做,,,目前没发现什么影响)
$ vim driver/clk/clk.c /*
修改
static bool clk_ignore_unused;
为
static bool clk_ignore_unused = true;
*/
//---编译运行
$ make uImage
//在移植不同版本的内核不一样 编译不行在后面添加地址试试
make uImage LOADADDR=0X40008000
$ make dtbs
$ cp arch/arm/boot/uImage /tftpboot
///exynos4412-tiny4412.dtb
$ cp arch/arm/boot/dts/exynos4412-fs4412.dtb /tftpboot/
//--设置板子参数
# setenv bootcmd tftp 41000000 uImage\;tftp 42000000 exynos4412-fs4412.dtb\;bootm 41000000 - 42000000 /* 设置tftp方式加载内核
setenv bootcmd 设置环境变量(自启动命令 bootcmd)
tftp 41000000 uImage\; 通过tftp从虚拟机/tftpboot目录下下载内核uImage到板子的内存 41000000 处。 \; 用于分割多个命令
tftp 42000000 exynos4412-fs4412.dtb 通过tftp下载设备树文件 exynos4412-fs4412.dtb 到板子的内存 42000000 处
bootm 41000000 - 42000000 启动内核(41000000处放的是内核uImage, 42000000处放的是设备树文件)
*/
# setenv bootargs root=/dev/nfs nfsroot=192.168.9.120:/nfs/rootfs rw console=ttySAC2,115200 init=/linuxrc ip=192.168.9.9 /* 挂载nfs rootfs
setenv bootarg 设置环境变量( bootarg是启动参数)
root=/dev/nfs 指定根文件系统类型是 nfs
nfsroot=192.168.9.120:/nfs/rootfs 指定nfs rootfs的位置 (是在ip 是192.168.9.120的机器上 ,的/nfs/rootfs目录下). 注意/nfs/rootfs必须和前面NFS服务配置文件设置一致
*/
# savenenv //保存环境变量
掉电重启动板子 /* 看能否挂载nfs rootfs成功
能看到下面信息表示成功
[root@farsight ]# ls
etc linuxrc proc sbin tmp var
bin dev lib mnt root sys usr
在里面创建文件,电脑的/nfs/rootfs上会同步变化
*/
}
第三方驱动移植(Linux当前的内核里没有的)
这里以LED驱动移植为例:
{//---------------------------------?LED驱动的移植
//---把驱动编译进内核uImage
$ cd linux-3.14
$ cp ~/e/fs4412/2系统移植/1实验/3第三天_内核移植/led/fs4412_led_drv.c drivers/char
//这就是下面移植的驱动文件
cp /mnt/hgfs/sharefile/fs4412_led_drv.c drivers/char/
$ vim drivers/char/Makefile /* 把驱动加入编译列表中
在末尾添加 obj-$(CONFIG_FS4412_LED) += fs4412_led_drv.o
*/
$ vim drivers/char/Kconfig /* 增加驱动的菜单配置选项(make menuconfig时能看到)
在menu "Character devices"下面 添加
config FS4412_LED
tristate "FS4412LED Device Support"
depends on ARCH_EXYNOS4
help
support led device on FS4412 develop board
*/
$ make menuconfig /* 配置编译驱动进内核
Device Drivers --->
Character devices --->
<*>FS4412 LED Device Support
*/
$ make uImage
make uImage LOADADDR=0X40008000
$ cp arch/arm/boot/uImage /tftpboot
//---测试驱动
$ cd ~/e/fs4412/2系统移植/1实验/3第三天_内核移植/led/
$ arm-none-linux-gnueabi-gcc fs4412_led_app.c //编译用于测试驱动的应用程序,默认编译会生成 a.out
$ cp a.out /nfs/rootfs
//cp led /nfs/rootfs
重启板子,进入根文件系统
# mknod /dev/led c 500 0 /*创建设备节点
mknod 专门用于创建设备节点的命令
/dev/led 是设备文件名
c 表示是字符设备
500 主设备号
0 次设备号
*/
# ./a.out //运行测试程序, 会看到灯闪烁
//---编译驱动为独立的模块
$ make menuconfig /* 配置驱动为模块
Device Drivers --->
Character devices --->
<M>FS4412 LED Device Support
*/
$ make uImage modules //编译内核 + 编译模块 (注: 驱动模块和内核是配对的)
$ cp arch/arm/boot/uImage /tftpboot/
$ cp drivers/char/fs4412_led_drv.ko /nfs/rootfs/
重启板子,进入根文件系统
# insmod fs4412_led_drv.ko
# mknod /dev/led c 500 0 /*创建设备节点
mknod 专门用于创建设备节点的命令
/dev/led 是设备文件名
c 表示是字符设备
500 主设备号
0 次设备号
*/
# ./a.out //运行测试程序, 会看到灯闪烁
}
编译驱动为独立的模块,独立模块就像搭积木一样,方便管理,(以后就使用这种方式)