文章目录
- 文章转载地址
- IMX6Q的SD卡启动使用教程【超完整】(1):uboot与kernel编译移植
- 一、准备启动SD卡
- 二、编译移植uboot
- 2.1 uboot下载
- 2.2 uboot编译
- 2.2.1 修改顶层Makefile
- 2.2.2 编译配置
- 2.2.3 编译
- 2.3 uboot烧录
- 三、编译移植kernel
- 3.1 kernel下载
- 3.2 kernel编译
- 3.2.1 编译方法
- 3.2.2 编译后的产物
- 四、kernel加载方法
- 4.1 TFTP方式加载kernel
- 4.1.1 方法简述
- 4.1.2 修改开发板IP
- 4.1.3 设置TFTP加载方式
- 4.2 SD卡加载kernel
- 五,根文件系统加载
- 5.1 制作根文件系统
- 5.2 NFS挂载根文件系统
- 5.2.1 方法简述
- 5.2.2 修改uboot环境变量
- 5.3 SD加载根文件系统
- 总结
- IMX6Q的SD卡启动使用教程【超完整】(2):busybox交叉编译根文件系统
文章转载地址
- IMX6Q的SD卡启动使用教程【超完整】(1):uboot与kernel编译移植
- IMX6Q的SD卡启动使用教程【超完整】(2):busybox交叉编译根文件系统
IMX6Q的SD卡启动使用教程【超完整】(1):uboot与kernel编译移植
本文主要介绍的是NXP官方开发板imx6q-sabresdSD卡烧写启动教程。
前言 本文操作环境为ubutnu18,需要准备好交叉编译工具链(本文不讨论)。启动资源版本:
- linux5.4
- uboot2021
注:
本文中,参考了正点原子IMX6ULL的教程,有些步骤不再详细描述,有时间会修改文章,进行详细补充。
一、准备启动SD卡
在进行资源编译移植时,需要准备一卡能够启动的SD卡,进行合适的SD卡分区与格式化。其过程主要使用到linux在的fdisk与mkfs工具。
本文不再介绍如何格式化SD卡,可参考大佬的教程:基于Ubuntu的linux环境制作嵌入式SD/TF启动卡
二、编译移植uboot
2.1 uboot下载
IMX6Q官方uboot地址为:https://source.codeaurora.org/external/imx/uboot-imx/
其中包括多个版本,供选下载,以下载最新的uboot2021为例:
下载命令为:
git clone https://source.codeaurora.org/external/imx/uboot-imx -b lf_v2021.04 --depth=1
下载结果为:
xxx@ubuntu:~/imx$ ls
uboot-imx
2.2 uboot编译
2.2.1 修改顶层Makefile
修改顶层Makefile,添加自己的交叉编译工具。如下图
2.2.2 编译配置
执行编译配置命令
make mx6qsabresd_defconfig
2.2.3 编译
执行编译命令
make -j4
编译完成后,在uboot顶层目录生成uboot镜像u-boot-dtb.imx。
2.3 uboot烧录
将生成的uboot镜像烧录至准备好的SD中,其命令为
sudo dd if=u-boot-dtb.imx of=/dev/sdb bs=512 seek=2 && sync
其中参数为含义为:
- dd:烧写命令
- if:需要烧录的文件(uboot镜像)
- of:被烧录的设备(SD卡)
- bs:扇区大小(一般默认都为512byte)
- seek:烧录至哪个扇区(IMX6Q为第二个扇区)
- sync:确保烧录完整
至此,将SD卡插入开发板,设置为SD启动,上电就能打印uboot的启动log。(疑问:如何设置SD卡启动?通过硬件拨码?)
三、编译移植kernel
3.1 kernel下载
IMX6Q官方linux地址为:https://source.codeaurora.org/external/imx/linux-imx/
其中包括多个版本,供选下载,以下载linux5.4为例,下载命令为
git clone https://source.codeaurora.org/external/imx/linux-imx -b imx_5.4.70_2.3.0 --depth=1
下载结果为
xxx@ubuntu:~/imx$ ls
linux-imx uboot-imx
3.2 kernel编译
3.2.1 编译方法
kernel编译使用脚本形式,在顶层目录下创建shell脚本文件
vim build.sh
build.sh脚本文件的内容为:
#!/bin/sh
#编译配置,第一次编译时使用,其他时候需屏蔽
make ARCH=arm imx_v7_defconfig CROSS_COMPILE=arm-none-eabi-
#编译
make ARCH=arm CROSS_COMPILE=arm-none-eabi- -j4
3.2.2 编译后的产物
执行完编译命令后,会生设备树与kernel的镜像,其路径分别为
设备树:linux-imx/arch/arm/boot/dts/imx6q-sabresd.dtb
kernel:linux-imx/arch/arm/boot/zImage
四、kernel加载方法
编译完成的kernel镜像,需要加载至DDR中运行,此过程有uboot完成,作为开发者只需要在uboot中配置好加载方式,一般的加载方法有
- TFTP加载(有网络)
- SD卡加载(无网络)
无论是哪种方式,只需要设置好uboot的环境变量即可。
4.1 TFTP方式加载kernel
在uboot启动后,进入交互模式,修改化境变量。修改uboot环境变量的命令主要有setenv、saveenv。
4.1.1 方法简述
IMX6Q uboot通过TFTP网络加载kernel,首先在虚拟机开启TFTP服务器,并创建TFTP文件夹,将kernel与设备树镜像拷贝至TFTP文件夹,此过程可参考正点原子教程。然后设置开发板的IP地址信息,最后使用ping命令,从虚拟机ping开发板。
其中设置虚拟机为TFTP服务器,并ping通开发板的步骤很重要,网上教程较多,限于文章篇幅,以后单独说明。
4.1.2 修改开发板IP
修改为自己环境的IP地址,命令为
#开发板IP,自己任意设置,但需要与主机同一网段
setenv ipaddr 169.254.xxx.xxx
setenv gatewayip 169.254.xxx.xxx
setenv netmask 255.255.255.0
#虚拟机即主机的IP,自己ifconfig参看
setenv serverip 169.254.xxx.xxx
#保存环境变量
saveenv
设置完IP后,重新启动,在虚拟机上ping开发板。能通,万事大吉!怎样都不通,不要放弃,参考SD加载kernel的方式,直接到4.2小节。
4.1.3 设置TFTP加载方式
修改环境变量,设置TFTP加载方式,涉及到的环境变量为bootcmd
#设置命令
setenv bootcmd 'tftpboot 0x15000000 zImage;tftpboot 0x14000000 imx6q-sabresd.dtb;bootz 0x15000000 - 0x14000000'
#保存环境变量
saveenv
上述内容中,主要分为三个步骤:
- tftpboot 0x15000000 zImage:从TFTP服务器加载内核镜像
- tftpboot 0x14000000 imx6q-sabresd.dtb:从TFTP服务器加载设备树
- bootz 0x15000000 - 0x14000000:启动内核
4.2 SD卡加载kernel
在无网络的情况下,使用此方法,会减少开发难度。
SD卡分区且格式化完成后,将kernel与设备树镜像拷贝至分区中(任意分区,推荐第一个分区)即可。默认的bootcmd环境变量,检索mmc下是否存在指定名称的kernel与设备设备镜像。
bootcmd=run findfdt;run findtee;mmc dev ${mmcdev};if mmc rescan; then if run loadbootscript; then run bootscript; else if run loadimage; then run mmcboot; else run netboot; fi; fi; else run netboot; fi
注: 看!SD卡加载kernel镜像的方式是不是很简单,只需要把镜像拷贝至SD中即可。 其实其过程uboot帮我们完成了工作,uboot,牛!
五,根文件系统加载
嵌入式系统的三大件:uboot、linux、rootfs,我们已经完成两步,只差rootfs了。
5.1 制作根文件系统
uboot、linux都是从NXP官网获取得到,而rootfs,需要我们自己的制作。
制作rootfs的方法有很多,使用最多最简单的就是通过交叉编译busybox得到幸。幸运是此教程网上较多,不在本文讨论,后续会另更新文章描述。
IMX6Q的SD卡启动使用教程【超完整】(2):busybox交叉编译根文件系统 本节主要介绍的是根文件系统加载方法,主要有
- NFS挂载(有网络)
- SD加载(无网络)
在uboot启动后,进入交互模式,修改化境变量,设置启动方式。
5.2 NFS挂载根文件系统
5.2.1 方法简述
此方法的前提是,开发板能够与虚拟机ping通。
IMX6Q 通过NFS挂载根文件系统,首先要在虚拟机开启NFS功能,此过程可参考正点原子教程。然后创建NFS目录,并根文件系统复制到NFS目录中。
虚拟机开启NFS功能,设置NFS挂载环境,网上教程较多,本文不再描述,后续系列文章会补充。(如果时间)
5.2.2 修改uboot环境变量
主要修改的是bootargs环境变量,根据自己的开发环境设置,其内容为
#1.先修改bootargs
setenv bootargs 'console=ttymxc0,115200 root=/dev/nfs nfsroot=169.254.17.100:/home/xxx/nfs,proto=tcp rw ip=169.254.17.229:169.254.17.100:169.254.17.1:255.255.255.0::eth0:off'
#2. 保存环境变量
saveenv
- console:串口参数
- root:kernel以NFS形式加载文件系统
- nfsroot:NFS参数,169.254.17.100为虚拟机地址,169.254.17.229为开发板地址
修改bootargs环境变量,并保存。重启开发板,成功加载根文件系统,进入shell交互,一顿ls操作,万事大吉!
5.3 SD加载根文件系统
如果网络不通,可使用SD加载根文件系统。修改uboot中的bootargs 与mmcargs环境变量
#1.先修改bootargs
setenv bootargs 'console=ttymxc0,115200 root=/dev/mmcblk2p2 rootwait rw'
#2.再修改mmcargs
setenv mmcargs 'console=ttymxc0,115200 root=/dev/mmcblk2p2 rootwait rw'
#3. 保存环境变量
saveenv
其中root=/dev/mmcblk2p2是文件系统存放的SD分区。本文将制作完成的rootfs拷贝到第二个SD分区中,因此设置为/dev/mmcblk2p2,根据个人情况设置。
总结
经过上述5个步骤,即可实现uboot引导linux,加载文件系统的工作。整个流程是一个linux嵌入式工程师必备技能,其中会遇到很多问题,需要自己一一解决并总结。幸运的是大部分问题网上都能找到解决方案,重要的是坚持!
后续会补充文中没有详细展开的内容,包括根文件系统制作、NFS\TFPT启动等。
还准备手把手教如何在IMX6Q上移植ubuntu20根文件系统并安装桌面,制作属于自己的嵌入式开发板环境。
IMX6Q的SD卡启动使用教程【超完整】(2):busybox交叉编译根文件系统
在上一篇文章【(1)uboot与kernel编译移植】中需要将自己的根文件系统通过NFS挂载或SD加载的形式来启动linux系统,本文将介绍如何制作是属于自己的根文件系统。
下载busybox资源 busybox下载地址为busybox资源,本教程下载版本为busybox-1.29.1.tar.bz2。
设置编译器 在交叉编译前,需要在虚拟机上准备好自己的交叉编译工具链,本文如下
export PATH=$PATH:/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabi/bin
解压压缩包
解压压缩包:tar -xvf busybox-1.29.1.tar.bz2
修改顶层Makefile
修改顶层Makefile,添加编译器与芯片架构信息:
#164行
CROSS_COMPILE ?= arm-linux-gnueabi-
#190行
ARCH ?= arm
配置menuconfig
- 根我们编译 Uboot、 Linux kernel 一样,我们要先对 busybox 进行默认的配置 。
make defconfig
- 配置menuconfig 执行make menuconfig
Location:
-> Settings
-> Build static binary (no shared libs)
Location:
-> Settings
-> vi-style line editing commands
Location:
-> Linux Module Utilities
-> Simplified modutils
Location:
-> Linux System Utilities
-> mdev (16 kb)//确保下面的全部选中,默认都是选中的
Location:
-> Settings
-> Support Unicode //选中
-> Check $LC_ALL, $LC_CTYPE and $LANG environment variables //选中
Location:
->Coreutils
->sync
Location:
->Linux System Utilities
->nsenter
编译与安装
执行编译命令:
make -j4
安装命令:
# CONFIG_PREFIX安装目录需要自己创建
make install CONFIG_PREFIX=/home/wcs/4412/rootfs/rootfs
添加库文件
- 向rootfs下/lib添加库 将编译器路径下的库,添加到向rootfs下/lib添加库。 先在rootfs下创建lib文件
mkdir lib
- 然后拷贝库文件
# 1.进入编译器库目录
cd /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabi/arm-linux-gnueabi/libc/lib
#2.拷贝库
cp *.so* *.a /home/wcs/4412/rootfs/rootfs/lib -d
# 3.进入编译器库目录
cd /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabi/arm-linux-gnueabi/lib
#4.拷贝库
cp *.so* *.a /home/wcs/4412/rootfs/rootfs/lib -d
- 向rootfs下/usr/lib添加库 先在rootfs的use下创建lib文件
mkdir lib
- 然后拷贝库文件
# 1.进入编译器库目录
cd /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabi/arm-linux-gnueabi/libc/usr/lib
#2.拷贝库
cp *.so* *.a /home/wcs/4412/rootfs/rootfs/usr/lib/ -d
至此文件系统已经移植完成,通过NFS挂载来验证,其结果为:
完善文件系统
- 在系统起来时,报can't run '/etc/init.d/rcS': No such file or directory,需创建文件/etc/init.d/rcS 。 rcS 是个 shell 脚本, Linux 内核启动以后需要启动一些服务,而 rcS 就是规定启动哪些文件的脚本文件。
# 1.创建etc目录
mkdir etc
# 2.创建init.d目录
mkdir init.d
# 3.创建rcS文件
vim rcS
# 4.rcS文件添加内容
#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin:$PATH#保存着可执行文件可能存在的目录
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/lib:/usr/lib#保存着库文件所在的目录
export PATH LD_LIBRARY_PATH
mount -a #命令来挂载所有的文件系统,这些文件系统由文件/etc/fstab 来指定
mkdir /dev/pts #创建目录/dev/pts,然后将 devpts 挂载到/dev/pts 目录中。
mount -t devpts devpts /dev/pts
mdev -s
# 5.修改权限
chmod 777 rcS
- 创建/etc/fstab文件 在 rootfs中创建/etc/fstab文件,fstab在Linux开机以后自动配置哪些需要自动挂载的分区,格式如下: :要挂载的特殊的设备,也可以是块设备,比如/dev/sda 等等。 :挂载点。 :文件系统类型,比如 ext2、ext3、proc、romfs、tmpfs 等等。 :挂载选项,在Ubuntu 中输入“man mount”命令可以查看具体的选项。一般使用 defaults,也就是默认选项,defaults 包含了 rw、suid、 dev、 exec、 auto、 nouser 和 async。 :为 1 的话表示允许备份,为 0 不备份,一般不备份,因此设置为 0。 :磁盘检查设置,为 0 表示不检查。根目录‘/’设置为 1,其他的都不能设置为 1,其他的分区从 2 开始。一般不在 fstab 中挂载根目录,因此这里一般设置为 0。
# 1.创建fstab文件
mkdir fdtab
# 2.添加内容
#<file system> <mount point> <type> <options> <dump> <pass>
proc /proc proc defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
sysfs /sys sysfs defaults 0 0
- 创建/etc/inittab文件 inittab 的详细内容可以参考 busybox 下的文件 examples/inittab。 init 程序会读取/etc/inittab这个文件, inittab 由若干条指令组成。
# 1.创建inittab文件
vim inittab
# 2.添加内容
#etc/inittab
::sysinit:/etc/init.d/rcS
console::askfirst:-/bin/sh
::restart:/sbin/init
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff -a
第 2 行,系统启动以后自动运行/etc/init.d/rcS 这个脚本文件。(可设置启动测试脚本) 第 3 行,将 console 作为控制台终端,也就是 ttymxc0。 第 4 行,重启的话运行/sbin/init。 第 5 行,按下 ctrl+alt+del 组合键的话就运行/sbin/reboot,看来 ctrl+alt+del 组合键用于重启系统。 第 6 行,关机的时候执行/bin/umount,也就是卸载各个文件系统。 第 7 行,关机的时候执行/sbin/swapoff,也就是关闭交换分区。
NFS挂载busybox
使用IMX6Q开发板,通过NFS挂载根文件系统。
- 设置虚拟机为NFS服务器。
- 修改uboot中的bootargs参数。
setenv bootargs 'console=ttymxc0,115200 root=/dev/nfs nfsroot=169.254.17.100:/home/wcs/nfs,proto=tcp rw ip=169.254.17.229:169.254.17.100:169.254.17.1:255.255.255.0::eth0:off'
- 169.254.17.229为开发板ip,169.254.17.100虚拟机ip
注: 本文参考正点原子以及网络教程
疑问:
- 如何打包到设备?
- 如何制作系统镜像、后续打包使用?