一. 前言
一直以来都是基于 Linux-2.6 内核学习嵌入式,但是工作之后发现,主流的 kernel 早已经不再使用 platform device 结构去描述设备信息了,而是换成了更为简洁的 device tree 方式。
这里贴出 wowotech 的 device tree 的引言:
作为一个多年耕耘在linux 2.6.23内核的开发者,各个不同项目中各种不同周边外设驱动的开发以及各种琐碎的、扯皮的俗务占据了大部分的时间。当有机会下载3.14的内核并准备学习的时候,突然发现linux kernel对于我似乎变得非常的陌生了,各种新的机制,各种framework、各种新的概念让我感到阅读内核代码变得举步维艰。 还好,剖析内核的热情还在,剩下的就交给时间的。首先进入视线的是Device Tree机制,这是和porting内核非常相关的机制,如果想让将我们的硬件平台迁移到高版本的内核上,Device Tree是一个必须要扫清的障碍。
参考文章:Device Tree 背景介绍
二. 移植 U-Boot
本小节主要是修改 U-Boot 源码,让其支持 dts 方式启动内核。
2.1 获取 U-Boot 源码
u-boot 使用的是友善之臂提供的 u-boot 源码,可以在友善之臂光盘获取。
U-Boot 源码光盘路径:Disk-A\uboot\uboot_tiny4412-20130729.tgz
我同时上传了一份到我的 github 上,可以通过 git clone 获取到。
1 | ## 克隆 git 仓库获取源码 |
2.2 修改源码以支持 dts 方式启动
前面已经提到,友善之臂光盘中提供的 u-boot 不支持引导 uImage 格式的 kernel,也不支持 device tree。针对这两个问题,对 u-boot 要做以下修改:
开启了 MMU 的话,u-boot 访问的都是虚拟地址,因为后期要使用 dnw 工具烧写文件到开发板 RAM 中,需要指定烧写到 RAM 中的具体物理地址,因此需要关闭 MMU。
1 | diff --git a/include/configs/tiny4412.h b/include/configs/tiny4412.h |
关闭 MMU 后,还需要修改 u-boot 的链接地址到真实物理地址范围内。
1 | diff --git a/board/samsung/tiny4412/config.mk b/board/samsung/tiny4412/config.mk |
开启设备树相关功能宏控,使其支持设备树。
1 | diff --git a/include/configs/tiny4412.h b/include/configs/tiny4412.h |
原生的 u-boot 使用 bootm 命令只可以引导 zImage 类型的 kernel,不支持 uImage,通过修改 bootm 命令可以使其支持 uImage。
1 | diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c |
2.3 安装交叉编译器
对于 kernel 和 u-boot 编译,最好使用同一个编译器,不妨在这 u-boot 编译之初,先配置一个同时支持 u-boot 以及 linux-4.4 版本的交叉编译器。
我个人使用的是 arm-none-eabi-gcc 编译器,可以访问 GNU Arm Embedded Toolchain 获取,也可以通过我的 git 仓库获取。
1 | ## 克隆 git 仓库获取交叉编译器 |
2.4 配置编译 U-Boot
修改 U-Boot 编译器为交叉编译器。
1 | diff --git a/Makefile b/Makefile |
配置编译 U-Boot。
1 | user@lenovo:~/workspace/tiny4412/uboot.support.dts$ make distclean |
2.5 烧写 U-Boot 到 SD 卡
在烧写的时候经常遇到这两个错误:
在 uboot 根目录下执行 sd_fusing.sh 脚本,报错如下:
1 | ## 在 uboot 根目录下执行 sd_fusing.sh 脚本 |
在 uboot 根目录下执行 sd_fusing.sh 脚本报错是因为脚本中使用的相对路径访问的 uboot 镜像,只有在 src/sd_fuse/tiny4412/ 目录下执行,路径才对的上。
另外找到 mkbl2 是因为执行 uboot 需要依赖 mkbl2。这个文件是三星官方给的,可以在 src/sd_fuse/ 目录下执行 make 生成。
1 | user@lenovo:~/workspace/tiny4412/uboot.support.dts/sd_fuse/tiny4412$ cd ../ |
正确的烧写流程:
1 | user@lenovo:~/workspace/tiny4412/uboot.support.dts$ cd sd_fuse/ |
将 u-boot 下载 SD 卡后,将 SD 卡插入 Tiny4412 中,使用 SD 启动方式,可以进入 u-boot 命令行。
1 | U-Boot 2010.12-00000-gef514bc-dirty (Mar 28 2018 - 21:58:58) for TINY4412 |
在 u-boot 中执行以下命令,可以将 u-boot 从 sd 中拷贝到 emmc 中,以后便可以通过 emmc 启动了。
但是很遗憾,我试验下来并不行,原因暂时没有找到。
1 | ## 将 u-boot 从 SD 卡复制到 DDR 中 |
三. 移植 Kernel
主要是配置好 dts 移植好 usb 网卡驱动,这些操作我都已经做好了,可以直接访问 github 获取。
具体的修改内容可以查看 github 仓库的提交记录。
1 | user@lenovo:~/workspace/tiny4412$ git clone git@github.com:tiny4412/linux-4.4.x.git |
四. 构建根文件系统
已经做好,可以直接访 github 获取。
1 | user@lenovo:~/workspace/tiny4412$ git clone git@github.com:tiny4412/rootfs.git |
如何使用呢?
- 开发板在 u-boot 中设置 bootargs 启动参数
1 | # nfs 启动方式的 root 属性格式为 nfsroot=<服务器IP地址>:<服务器上的文件目录> ip=<开发板IP地址>:<服务器IP地址>:<网关>:<子网掩码>::eth0:off |