一、Linux移植三巨头:uboot、Linux kernel、rootfs(根文件系统)。
1.Uboot
Linux 系统要启动就必须需要一个 bootloader 程序,也就说芯片上电以后先运行一段 bootloader 程序。
这段bootloader程序会先初始化DDR等外设,然后将Linux内核从flash(NAND, NOR FLASH,SD,MMC 等)拷贝到 DDR 中,最后启动 Linux 内核。
当然了,bootloader 的实 际工作要复杂的多,但是它最主要的工作就是启动 Linux 内核
直接使用正点原子已经移植好的 uboot,这个已经放到了开发 板光盘中了,路径为:开发板光盘->1、程序源码->3、正点原子 Uboot 和 Linux 出厂源码->ubootimx-2016.03-2.1.0-ge468cdc-v1.5.tar.bz2
uboot编译与烧写,通过SD卡烧写。具体烧写步骤见附件一。
2.Linux kernel
包括
①Linux内核镜像文件:zImage
②I.MX6ULL EVK开发板对应的设备树文件:imx6ull-14×14-evk.dtb
3.rootfs(根文件系统)
二、内核和根文件系统下载:
tftp 从 Ubuntu 中下载 zImage 和设备树文件,通过 nsf 挂载根文件系统;
为了方便调试,一般通过网络方式启动 Linux,如果每次修改 Linux 系统文件或者 linux 下的某个驱动以后都要将其烧写到 EMMC 中去测试,这样太麻烦;
只需将 linux 镜像文件和根文件系统都放到 Ubuntu 下,这样每次重新编译 linux 内核或者某个 linux 驱动,只需 cp 将其拷贝到这个指定的文件夹中即可;nsf和tftp安装配置流程见附件二。
具体步骤为:
/home/abc/linux/tftp 文件夹下准备好 imx6ull-alientek-emmc.dtb 设备树、zImage 内核镜像
/home/abc/linux/nfs 文件夹下准备好rootfs 根文件系统
下载时需要配置uboot 网络环境变量。配置网络环境变量步骤见附件三。
附件一:
uboot编译与烧写:
首先在 Ubuntu 中安装 ncurses 库,否则编译会报错,安装命令如下:
sudo apt-get install libncurses5-dev
在 Ubuntu 中创建存放 uboot 的目录,比如我的是/home/$USER/linux/uboot,然后在此目录 下新建一个名为“alientek_uboot”的文件夹用于存放正点原子提供的 uboot 源码。alientek_uboot 文件夹创建成功以后使用 FileZilla 软件将正点原子提供的 uboot 源码拷贝到此目录中,正点原 子提供的 uboot 源码已经放到了开发板光盘中,路径为:开发板光盘->1、例程源码->3、正点原 子 Uboot 和 Linux 出厂源码-> uboot-imx-2016.03-2.1.0-ge468cdc-v1.5.tar.bz2。
将其拷贝到 Ubuntu 中新建的 alientek_uboot 文件夹下
使用如下命令对其进行解压缩:
tar -vxjf uboot-imx-2016.03-2.1.0-g8b546e4.tar.bz2
如果使用的是 512MB+8GB 的 EMMC 核心板,使用如下命令来编译对应的 uboot:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- (加空格) mx6ull_14x14_ddr512_emmc_defconfig
make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j12
这三条命令中 ARCH=arm 设置目标为 arm 架构,CROSS_COMPILE 指定所使用的交叉编 译器。第一条命令相当于“make distclean”,目的是清除工程,一般在第一次编译的时候最好清 理一下工程。第二条指令相当于“make mx6ull_14x14_ddr512_emmc_defconfig”,用于配置 uboot, 配置文件为 mx6ull_14x14_ddr512_emmc_defconfig。最后一条指令相当于 “make -j12”也就是 使用 12 核来编译 uboot。当这三条命令执行完以后 uboot 也就编译成功了
可以看出,编译完成以后 uboot 源码多了一些文件,其中 u-boot.bin 就是编译出来的 uboot 二进制文件。uboot是个裸机程序,因此需要在其前面加上头部(IVT、DCD等数据)才能在I.MX6U 上执行,图 30.2.4 中的 u-boot.imx 文件就是添加头部以后的 u-boot.bin,u-boot.imx 就是我们最 终要烧写到开发板中的 uboot 镜像文件。
每次编译 uboot 都要输入一长串命令,为了简单起见,我们可以新建一个 shell 脚本文件, 将这些命令写到 shell 脚本文件里面,然后每次只需要执行 shell 脚本即可完成编译工作。新建 名为 mx6ull_alientek_emmc.sh 的 shell 脚本文件,然后在里面输入如下内容:
示例代码 30.2.1 mx6ull_alientek_emmc.sh 文件代码
#!/bin/bash
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- (加空格) mx6ull_14x14_ddr512_emmc_defconfig
make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j12
第 1 行是 shell 脚本要求的,必须是“#!/bin/bash”或者“#!/bin/sh”。 第 2 行使用了 make 命令,用于清理工程,也就是每次在编译 uboot 之前都清理一下工程。 这里的 make 命令带有三个参数,第一个是 ARCH,也就是指定架构,这里肯定是 arm;第二个 参数 CROSS_COMPILE 用于指定编译器,只需要指明编译器前缀就行了,比如 arm-linuxgnueabihf-gcc 编译器的前缀就是“arm-linux-gnueabihf-”;最后一个参数 distclean 就是清除工程。 第 3 行也使用了 make 命令,用于配置 uboot。同样有三个参数,不同的是,最后一个参数 是 mx6ull_14x14_ddr512_emmc_defconfig。前面说了 uboot 是 bootloader 的一种,可以用来引导 Linux,但是 uboot 除了引导 Linux 以外还可以引导其它的系统,而且 uboot 还支持其它的架构 和外设,比如 USB、网络、SD 卡等。这些都是可以配置的,需要什么功能就使能什么功能。所 以在编译 uboot 之前,一定要根据自己的需求配置 uboot。mx6ull_14x14_ddr512_emmc_defconfig 就是正点原子针对 I.MX6U-ALPHA 的 EMMC 核心板编写的配置文件,这个配置文件在 uboot 源码的 configs 目录中。在 uboot 中,通过“make xxx_defconfig”来配置 uboot,xxx_defconfig 就是不同板子的配置文件,这些配置文件都在 uboot/configs 目录中。 第 4 行有 4 个参数,用于编译 uboot,通过第 3 行配置好 uboot 以后就可以直接“make”编 译 uboot 了。其中 V=1 用于设置编译过程的信息输出级别;-j 用于设置主机使用多少线程编译 uboot,最好设置成我们虚拟机所设置的核心数,如果在 VMware 里面给虚拟就分配了 4 个核, 那么使用-j4 是最合适的,这样 4 个核都会一起编译。 使用 chmod 命令给予 mx6ull_alientek_emmc.sh 文件可执行权限,然后就可以使用这个 shell 脚本文件来重新编译 uboot,命令如下:
./mx6ull_alientek_emmc.sh
U-Boot 烧写与启动
V- uboot 编译好以后就可以烧写到板子上使用了,这里我们跟前面裸机例程一样,将 uboot 烧写到 SD 卡中,然后通过 SD 卡来启动来运行 uboot。使用 imxdownload 软件烧写,命令如 下:
chmod 777 imxdownload //给予 imxdownload 可执行权限,一次即可
./imxdownload u-boot.bin /dev/sdd //烧写到 SD 卡,不能烧写到/dev/sda 或 sda1 设备里面!
等待烧写完成,完成以后将 SD 卡插到 I.MX6U-ALPHA 开发板上,BOOT 设置从 SD 卡启 动,使用 USB 线将 USB_TTL 和电脑连接,也就是将开发板的串口 1 连接到电脑上。打开 MobaXterm,设置好串口参数并打开,最后复位开发板。在 MobaXterm 上出现“Hit any key to stop autoboot: ”倒计时的时候按下键盘上的回车键,默认是 3 秒倒计时,在 3 秒倒计时结束以 后如果没有按下回车键的话 uboot 就会使用默认参数来启动 Linux 内核了。如果在 3 秒倒计时 结束之前按下回车键,那么就会进入 uboot 的命令行模式
附件二:
nsf 和 tftp 安装配置:
配置工作基本分为四部分:
①安装
②指定nsf服务器目录
③修改nsf配置文件
④重启
1.1 nsf
一般Linux 驱动在开发中通过 nfs(Network File System) 挂载根文件系统,当产品最终上市开卖的时候才会将根文件系统烧写到 EMMC 或者 NAND 中。
① 安装 NFS 服务:
sudo apt-get install nfs-kernel-server rpcbind
② 在 linux 下 创建nfs 文件夹供 nfs 服务器使用:
mkdir /home/abc/linux/nfs
③ 修改nfs配置文件:
sudo vi /etc/exports
在最后添加:
/home/abc/linux/nfs *(rw,sync,no_root_squash)
④ 重启 NFS 服务,使用命令如下:
sudo /etc/init.d/nfs-kernel-server restart
⑤ 检查nfs服务器中挂载的目录。
showmount -e
配置到此结束,接下来就是在nfs目录下构件根目录系统。
1.2 tftp
tftp(Trivial File Transfer Protocol) 命令的作用和 nfs 命令一样,都是用于通过网络下载东西到 DRAM 中,只是 tftp 命令使用的 TFTP 协议,Ubuntu 主机作为 TFTP 服务器。
① 安装:
sudo apt-get install tftp-hpa tftpd-hpa
sudo apt-get install xinetd
1
2
② 在 linux 下 创建 tftp 文件夹供 tftp 服务器使用, 并给权限:
mkdir /home/chunn/linux/tftpboot
chmod 777 /home/chunn/linux/tftpboot
1
2
③ 修改 tftp 的配置文件:
sudo vi /etc/xinetd.d/tftp
/etc/xinetd.d/tftp
server tftp
{
socket_type = dgram #socket的链接类型是dgram(UDP)
protocol = udp #UDP协议
wait = yes #等待到启动完成
disable = no #yes表示TFTP服务器是关闭的;no表示启动TFTP服务器
user = root #指定root用户启动服务进程
server = /usr/sbin/in.tftpd #指定服务进程是/usr/sbin/in.tftpd
server_args = -s /home/chunn/linux/tftp -c #指定传给该进程的参数(确定目录)
#log_on_success += PID HOST DURATION
#log_on_failure += HOST
per_source = 11 #表示每一个ip地址上最多可以建立的实例数目
cps =100 2 #表示每秒100个入站链接,如果超过限制,则等待2秒
flags =IPv4 #IPv4网络
}
④ 修改tftp-hpa 的配置文件:
sudo vi /etc/default/tftpd-hpa
/etc/default/tftpd-hpa
TFTP_USERNAME=“tftp”
TFTP_DIRECTORY=“/home/chunn/linux/tftp” #TFTP服务器的目录设置
TFTP_ADDRESS=“:69” #ip地址和端口号
TFTP_OPTIONS=“–secure”
⑤ 重启tftp
sudo service tftpd-hpa restart
附件三:
uboot 环境变量配置(实现tftp 从 Ubuntu 中下载 zImage 和设备树文件,通过 nsf 挂载根文件系统)
使用SecureCRT进入uboot, 输入uboot 指令进行网络环境变量设置
2.1 设置IP
setenv ethaddr 00:04:9f:04:d2:35 //硬件地址
setenv gatewayip 192.168.100.1 //网关
setenv ipaddr 192.168.100.103 //开发板的IP地址
setenv netmask 255.255.255.0 //子网掩码
setenv serverip 192.168.100.102 //Ubuntu的IP地址(可以通过ifconfig查询)
saveenv //保存环境变量
2.2 设置bootcmd (tftp下载zImage和设备树)
bootcmd: 其名分为 “boot” 和 “cmd”,也就是“引导”和“命令”,其实就是启动的命令集合, 如下为使用 tftp 从网络启动 Linux(验证通过的):
setenv bootcmd ‘tftp 80800000 zImage; tftp 83000000 imx6ull-alientek-emmc.dtb; bootz 80800000 - 83000000’
saveenv
● bootcmd 设置的内容:
- tftp 80800000 zImage : (tftpboot [loadAddress] [[hostIPaddr:]bootfilename] )
将 tftpboot 文件夹里面的 zImage 文件下载到DRAM的0X80800000地址处;
- tftp 83000000 imx6ull-alientek-emmc.dtb;
将设备树imx6ull-14x14-emmc-7-1024x600-c.dtb 下载到 DRAM 中的 0X83000000 地址处
- bootz 80800000 - 83000000
使用命令 bootz 启动
● 指令:
setenv bootcmd : 设置bootcmd 变量,后续有空格,所以加上引号
saveenv : 保存环境变量
● 注意:
-
Ubuntu 中创建 tftpboot 目录的时需要给予 tftboot 相应的权限。
-
tftpboot 目录中要下载的文件没有给予相应的权限
使用命令“chmod 777 xxx”来给予权限,其中“xxx”就是要给予权限的文件或文件夹
2.3 设置bootargs (从nfs 挂载根文件系统)
bootargs 保存着 uboot 传递给 Linux 内核的参数,主要用来告诉内核分区信息和根文件系统所在的分区等
setenv bootargs ‘console=ttymxc0,115200 root=/dev/nfs rw nfsroot=192.168.0.102:/home/chunn/linux/nfs/rootfs ip=192.168.0.103:192.168.0.102:192.168.0.1:255.255.255.0::eth0:off’
saveenv
nfs 挂载的 bootargs 格式如下:
root=/dev/nfs nfsroot=[:][,] ip=::::::::
:服务器 IP 地址,也就是存放根文件系统主机的 IP 地址,那就是 Ubuntu 的 IP
地址,比如我的 Ubuntu 主机 IP 地址为 192.168.0.102。
:根文件系统的存放路径,比如我的就是/home/chunn/linux/nfs/rootfs。
:NFS 的其他可选选项,一般不设置。
:开发板的 IP 地址,Linux 内核启动以后就会使用此 IP 地址来配置开发板。此地址一定要和 Ubuntu 主机在同一个网段内,在 Ubuntu 中使用 ping 命令 ping 一下就知道要设置的 IP 地址有没有被使用,如果不能 ping 通就说明没有被使用,那么就可以设置为开发板的 IP 地址,比如我就可以设置为 192.168.0.103。
:服务器 IP 地址,前面已经说了。
:网关地址,我的就是 192.168.0.1。
:子网掩码,我的就是 255.255.255.0。
:客户机的名字,一般不设置,此值可以空着。
:设备名,也就是网卡名,一般是 eth0,eth1….,正点原子的 I.MX6U-ALPHA 开发板的 ENET2 为 eth0,ENET1 为 eth1。如果你的电脑只有一个网卡,那么基本只能是 eth0。 这里我们使用 ENET2,所以网卡名就是 eth0。
:自动配置,一般不使用,所以设置为 off。
:DNS0 服务器 IP 地址,不使用。
:DNS1 服务器 IP 地址,不使用。
其它解释:
1)console=ttymxc0,115200 :ttymxc0(也就是串口 1)作为 Linux 的终端,并且串口波特率设置为 115200
2)“rw” : 表示 nfs 挂载的根文件系统为可读可写。
附件四:
过程梳理
1)在ubuntu 中 配置好nsf、tftp服务,关键步骤:
sudo vi /etc/exports //nfs配置
sudo vi /etc/xinetd.d/tftp //tft配置
sudo vi /etc/default/tftpd-hpa //tftpd-hpa配置
2)/home/chunn/linux/tftp 文件夹下准备好 imx6ull-alientek-emmc.dtb 设备树、zImage 内核镜像;
3)/home/chunn/linux/nfs 文件夹下准备好rootfs 根文件系统
3)设置 uboot 的IP环境变量:
setenv ethaddr 00:04:9f:04:d2:35 //硬件地址
setenv gatewayip 192.168.1.1 //网关
setenv ipaddr 192.168.1.103 //开发板的IP地址
setenv netmask 255.255.255.0 //子网掩码
setenv serverip 192.168.1.102 //Ubuntu的IP地址(可以通过ifconfig查询)
saveenv //保存环境变量
4)设置 uboot 的 bootcmd 和 bootargs 环境变量 :
setenv bootcmd ‘tftp 80800000 zImage; tftp 83000000 imx6ull-alientek-emmc.dtb; bootz 80800000 - 83000000’
setenv bootargs ‘console=ttymxc0,115200 root=/dev/nfs rw nfsroot=192.168.0.102:/home/chunn/linux/nfs/rootfs ip=192.168.0.103:192.168.0.102:192.168.0.1:255.255.255.0::eth0:off’
saveenv