IMX6Q的SD卡启动使用教程

文章转载地址

IMX6Q的SD卡启动使用教程【超完整】(1):uboot与kernel编译移植

本文主要介绍的是NXP官方开发板imx6q-sabresdSD卡烧写启动教程。

前言
本文操作环境为ubutnu18,需要准备好交叉编译工具链(本文不讨论)。启动资源版本:

  • linux5.4
  • uboot2021

注:

本文中,参考了正点原子IMX6ULL的教程,有些步骤不再详细描述,有时间会修改文章,进行详细补充。

一、准备启动SD卡

在进行资源编译移植时,需要准备一卡能够启动的SD卡,进行合适的SD卡分区与格式化。其过程主要使用到linux在的fdiskmkfs工具。

本文不再介绍如何格式化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环境变量的命令主要有setenvsaveenv

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

上述内容中,主要分为三个步骤:

  1. tftpboot 0x15000000 zImage:从TFTP服务器加载内核镜像
  2. tftpboot 0x14000000 imx6q-sabresd.dtb:从TFTP服务器加载设备树
  3. 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,牛!

五,根文件系统加载

嵌入式系统的三大件:ubootlinuxrootfs,我们已经完成两步,只差rootfs了。

5.1 制作根文件系统

ubootlinux都是从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中的bootargsmmcargs环境变量

#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挂载根文件系统。

  1. 设置虚拟机为NFS服务器。
  2. 修改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

注:
本文参考正点原子以及网络教程

疑问:

  • 如何打包到设备?
  • 如何制作系统镜像、后续打包使用?

猜你喜欢

转载自blog.csdn.net/mayue_web/article/details/130359170