imx6ull移植Linux系统第一篇——U-Boot的移植

imx6ull移植Linux系统第一篇——U-Boot的移植

  花了大概两周的时间,把Linux的移植认真学了一遍,期间踩了不少坑,花费了不少时间去解决各种奇奇怪怪的问题,最终完成了uboot、系统镜像、设备树以及根文件系统的制作,并最终下载到开发板上运行。这里想对这两周的学习内容进行一个总结,因为后期会有其他的学习安排,系统移植是一些经验和方法的掌握,如果长时间不去用,时间久了肯定会忘,希望这里写的总结会对后期的移植工作给出一些方法上的参考。


提示:本系列文档共分四篇:U-Boot的移植、Linux内核的移植、根文件系统的构建、系统烧写,本文为第一篇U-Boot的移植。

文章目录

  • imx6ull移植Linux系统第一篇——U-Boot的移植
  • 前言
  • 一、什么是U-Boot
  • 二、U-Boot的常用命令
    • 2.1 信息查询命令:print、bdinfo、version
    • 2.2 修改环境变量:setenv、saveenv
    • 2.3 内存操作命令
    • 2.4 网络操作命令
    • 2.5 EMMC和SD卡操作命令
    • 2.6 FAT格式文件系统操作命令
    • 2.7 BOOT操作命令
  • 三、 编译和下载uboot
    • 3.1 uboot的编译
    • 3.2 uboot的烧写
  • 四、移植自己的uboot
    • 4.1 添加开发板默认配置文件
    • 4.2 添加开发板对应的头文件
    • 4.3. 添加开发板对应的板级文件夹
    • 4.4 修改U-Boot图形配置界面
    • 4.5 LCD驱动、网络驱动的修改
    • 4.6 其他修改
  • 五、配置uboot环境变量
    • 5.1 关于bootargs的配置
    • 5.2 关于bootcmd的配置
  • 总结


前言

  Linux系统主要由四部分组成:uboot(.imx)、系统镜像(zImage)、设备树(.dtb)以及根文件系统(rootfs),所以我们要制作这四个文件,但是系统镜像和设备树是通过编译内核源码时同时得到的,所以主要的配置工作就只有三个,加上最后的烧写方法,一共分为四部分来总结。


提示:本文是根据正点原子imx6ull开发板教程,参考NXP官方EVK开发板源码做的移植工作,结合自己的一些理解所做的一些总结。

一、什么是U-Boot

  Linux系统上电以后需要一个bootloader程序引导来芯片运行,它分为 bootloader 两个阶段,主要就是初始化DDR,将Linux内核从flash中拷贝到DDR,然后启动Linux内核,相当于Windows上的BIOS。这段代码是十分复杂的,但是现在有很多现成的bootloader,其中使用最广泛的就是U-Boot,它是遵循GPL开源协议的软件,也可以看成一段引导内核运行的裸机代码。
  半导体厂商会根据uboot官方的U-Boot源码来移植适配自家的芯片,所以我们可以从半导体厂商维护的uboot来移植到我们自己的系统上,NXP 就 维 护 的 2016.03 这 个 版 本 的 uboot 。

二、U-Boot的常用命令

  Linux系统开机时会先运行uboot代码,在bootdelay倒计时结束前,按下回车键,系统就会进入uboot命令行模式,在命令行里我们可以对uboot进行一些查询、配置的工作。

2.1 信息查询命令:print、bdinfo、version

  用的最多的就是 print 命令了,它可以打印出当前uboot的信息,我们可以用print来查看配置的环境变量是否正确。version用来查询uboot的版本号。

2.2 修改环境变量:setenv、saveenv

  setenv用于设置或修改环境变量的值saveenv用于保存环境变量的值。要注意setenv修改的是DRAM中的环境变量值,修改完要用saveenv将修改的环境变量保存到flash中,否则下次重启还是之前的环境变量值。

2.3 内存操作命令

  用到的不多,不作介绍了。

2.4 网络操作命令

  uboot是支持网络的,如果需要设置NFS启动根文件系统,我们就需要在uboot中配置IP信息(uboot中配置的IP貌似只在uboot中启动有效,因为在Linux系统中还需要重新配置),具体命令如下:

setenv ipaddr 192.168.1.50
setenv ethaddr 00:04:9f:04:d2:35
setenv gatewayip 192.168.1.1
setenv netmask 255.255.255.0
setenv serverip 192.168.1.180
saveenv

  上述分别是开发板IP地址、开发板MAC地址、网关地址、子网掩码和服务器IP地址,如果开发板和主机想要ping通,二者必须设置在同一网段下(同一网段指的是IP地址和子网掩码相与得到相同的网络地址)。
  设置好uboot的IP信息,并且将电脑和开发板连接到同一路由器或者交换机上以后(电脑设置成静态IP以后,可以用网线直连开发板和电脑),就可以在uboot中ping主机IP地址,注意uboot中的网络服务是单向的,只能在uboot中ping其他机器,所以电脑ping不通uboot是正常现象。如果uboot可以ping通电脑,就说明网络的连接是没有问题的。

2.5 EMMC和SD卡操作命令

  一般认为EMMC和SD卡是同一种东西,这里统称MMC,用mmc info可以看到设备0是SD卡,设备1是EMMC。如果EMMC里面烧写了Linux系统的话,EMMC会有三个分区:第 0 个分区存放 uboot,第 1 个分区存放 Linux 镜像文件和设备树,第 2 个分区存放根文件系统,但是第0个分区没有格式化,所以用mmc part只能查询到1、2分区;一个新的SD卡只有一个分区0,所以uboot只能烧写到SD卡的分区0,后面移植内核时,SD卡会被烧写工具格式化出第二个分区用来存放Linux镜像文件和设备树。
  uboot中用mmc命令操作MMC设备。我在移植uboot时,主要用到 ls mmc 1:1,用来查询EMMC上的Linux镜像文件和设备树,其他命令见下图:
imx6ull移植Linux系统第一篇——U-Boot的移植_第1张图片

2.6 FAT格式文件系统操作命令

  这里主要用到fatload命令来设置bootcmd,其它的比如fatinfo、fatls、fstype、fatwrite的用法参考手册。
  fatload用于将指定文件读取到DRAM中,比如我们将EMMC分区1中的zImage文件读取到DRAM中的80800000地址处,命令如下:

fatload mmc 1:1 80800000 zImage

  这里的1:1就是设备1的分区1,即EMMC的分区1,前面说过分区1放的就是Linux镜像(zImage)和设备树文件(.dtb)。

2.7 BOOT操作命令

  uboot的本质工作室用来引导Linux,所以肯定需要有相关的boot引导命令来启动Linux,常用的有bootz、bootm和boot,因为在设置bootcmd最后需要用到bootz,所以这里主要介绍bootz
  bootz命令用于启动zImage镜像文件,假设我们已经通过上述的fatload命令将镜像zImage下载的了DRAM中的0x80800000处,将设备树imx6ull-alientek-emmc.dtb下载到了DRAM的0x83000000处,这时我们就可以用bootz启动镜像文件:

bootz 80800000 - 83000000

三、 编译和下载uboot

  编译和下载的方法是固定的,这里我们拿原厂uboot来说明编译下载的方法。需要先将NXP的uboot文件ubootimx-rel_imx_4.1.15_2.1.0_ga.tar.bz2在Ubuntu下解压缩,解压命令为:tar -vxjf 文件名.tar.bz2

3.1 uboot的编译

  我们可以写一个shell脚本来执行所需的指令,在解压后的uboot文件中创建mx6ull_14x14_evk_emmc.sh脚本,然后输入如下内容:

#!/bin/bash
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihfmx6ull_14x14_evk_emmc_defconfig
make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j16

  然后用chmod赋予该脚本可执行权限,输入命令./mx6ull_14x14_evk_emmc.sh就可以自动编译,完成后生成u-boot.bin。这里有一个坑,特此说明:不要使用apt-get install自动安装最新的交叉编译器,否则会发生编译正常,但实际运行时网络异常的现象!!!如果你的交叉编译器是自动安装的,那需要先卸载,然后按照正点原子的教程安装低版本的交叉编译器,每次编译时先用 sudo -s 进入 root 模式之后再进行编译,这样才不会出问题。

3.2 uboot的烧写

编译好的u-boot.bin还需要添加头部文件才能成为最终烧写到芯片上的u-boot.imx文件,由于具体的添加过程比较繁琐,也不是我们学习的重点,所以正点原子直接做了一个imxdownload软件。我们需要将这个imxdownload文件复制到当前的目录中,然后将SD卡插入电脑,连接到虚拟机上,用lsblk命令查看这个SD卡的名字,我的查询结果是sdb,最后输入烧写命令:

sudo ./imxdownload u-boot.bin /dev/sdb

  注意:这里是对u-boot.bin进行操作,经过imxdownload处理以后会在当前目录下生成u-boot.imx,并且会自动将u-boot.imx烧写进SD卡。此处也有一个坑:若下载速度过快,一般都是下载失败了,但在终端上却提示成功,而实际在开发板上运行却没有反应,这个问题尚不知道如何解决,只能将Ubuntu重启,正常的下载速度应该是十几秒。

四、移植自己的uboot

  移植uboot其实就是改写NXP原厂的uboot,主要需要修改自己的文件名、个别不同于原厂的器件等,这里依次说明要修改的地方。

4.1 添加开发板默认配置文件

  在目录 configs 下,复制mx6ull_14x14_evk_emmc_defconfig,然后重命名为mx6ull_alientek_emmc_defconfig,内容修改为:

CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/freescale/mx6ull_alientek_emmc/imximage.cfg,MX6ULL_EVK_EMMC_REWORK"
CONFIG_ARM=y 
CONFIG_ARCH_MX6=y 
CONFIG_TARGET_MX6ULL_ALIENTEK_EMMC=y 
CONFIG_CMD_GPIO=y

  注意第一行的最后MX6ULL_EVK_EMMC_REWORK不要修改,因为会关联到其他的文件,修改后会导致芯片uboot读不到mmc而报错。

4.2 添加开发板对应的头文件

  在目录 include/configs 下,添加我们定制开办板的头文件,复 制include/configs/mx6ullevk.h,并重命名为 mx6ull_alientek_emmc.h,然后将文件里面的

#ifndef __MX6ULLEVK_CONFIG_H
#define __MX6ULLEVK_CONFIG_H

  修改为:

#ifndef __MX6ULL_ALIENTEK_EMMC_CONFIG_H
#define __MX6ULL_ALIENTEK_EMMC_CONFIG_H

  头文件mx6ull_alientek_emmc.h里面有很多用于配置uboot的宏定义,后面还会继续用到。

4.3. 添加开发板对应的板级文件夹

  目录board/freescale是存放I.MX系列芯片的板级文件的,比如外设驱动等,这里我们需要复制该目录下的mx6ullevk,重命名为mx6ull_alientek_emmc,然后修改内部的一些文件:

  • 修改mx6ull_alientek_emmc目录下的Makefile文件
    修改为:
# (C) Copyright 2015 Freescale Semiconductor, Inc. 
# 
# SPDX-License-Identifier: GPL-2.0+ 
# 
obj-y := mx6ull_alientek_emmc.o
extra-$(CONFIG_USE_PLUGIN) := plugin.bin
$(obj)/plugin.bin: $(obj)/plugin.o
$(OBJCOPY) -O binary --gap-fill 0xff $< $@

  主要就是第6行。

  • 修改imx6ull_alientek_emmc目录下的imximage.cfg文件
PLUGIN board/freescale/mx6ullevk/plugin.bin 0x00907000

  修改为:

PLUGIN board/freescale/mx6ull_alientek_emmc /plugin.bin 0x00907000
  • 修改 mx6ull_alientek_emmc 目录下的 Kconfig 文件
    修改后的内容如下:
if TARGET_MX6ULL_ALIENTEK_EMMC

config SYS_BOARD
default "mx6ull_alientek_emmc"

config SYS_VENDOR
default "freescale"

config SYS_SOC
default "mx6"

config SYS_CONFIG_NAME
default "mx6ull_alientek_emmc"

endif
  • 修改mx6ull_alientek_emmc目录下的MAINTAINERS文件
    修改后的内容如下:
MX6ULL_ALIENTEK_EMMC BOARD
M: Peng Fan <peng.fan@nxp.com> 
S: Maintained
F: board/freescale/mx6ull_alientek_emmc/ 
F: include/configs/mx6ull_alientek_emmc.h

4.4 修改U-Boot图形配置界面

  修改文件arch/arm/cpu/armv7/mx6/Kconfig,在207行加入如下这句话:

config TARGET_MX6ULL_ALIENTEK_EMMC
bool "Support mx6ull_alientek_emmc"
select MX6ULL
select DM
select DM_THERMAL

  在最后一行的endif的前一行加入:

source "board/freescale/mx6ull_alientek_emmc/Kconfig"

4.5 LCD驱动、网络驱动的修改

  由于使用了不同的分辨率的LCD屏幕,所以需要结合LCD屏幕的参数对驱动的像素、刷新率等进行修改,详细的修改方法见正点原子教程。
  对于网络驱动部分,NXP原厂开发板用的是KSZ8081 PHY芯片,而实际上LAN8720更为常用,也更便宜,而且IEEE联盟规定了所有使用TCP的网络PHY芯片的前15引脚必须相同,也就是说我们只需要修改一些辅助功能的引脚,就可以将KSZ8081修改为PHY8720芯片。这里主要需要修改芯片的复位引脚和芯片厂商,具体见正点原子教程。

4.6 其他修改

  uboot启动时会打印“Board: MX6ULL 14x14 EVK”这一句,我们可以把打印的开发板名字修改成我们自己的,打开文件 mx6ull_alientek_emmc.c,找到函数checkboard,将其改为如下所示内容:

int checkboard(void) {
     
if (is_mx6ull_9x9_evk())
puts("Board: MX6ULL 9x9 EVK\n");
else
puts("Board: MX6ULL ALIENTEK EMMC\n");
return 0;
}

五、配置uboot环境变量

  uboot里面有两个很重要的很重要的环境变量 bootargsbootcmd,我们在运行uboot时往往需要先规定这两个环境变量的值,让uboot以某种规则启动内核。可以在uboot命令行中配置,也可以直接在uboot的配置文件中修改。

5.1 关于bootargs的配置

  bootargs中保存着uboot传递给Linux内核的参数,主要包含以下几个:

  • console:用来设置Linux终端,即设置与Linux交互的方式,如我们一般选择串口作为终端,那么console设置为/dev/ttymxc0;
  • root:用来设置根文件的位置,若设置为/dev/mmcblk1p2,则表示设置根文件位置为EMMC的分区2。root后面有“rootwait rw”,表示等待mmc设备初始化完成以后再挂载,并且根文件系统是可读可写的;
  • rootfstype:用来指定根文件系统的类型,如果根文件系统为ext 格式的话此选项无所谓。
    我们可以通过下面这句话配置板子以串口为终端、设置根文件:
setenv bootargs 'console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw'

  也可以通过下面这几句话,通过NFS从Ubuntu主机加载根文件系统,前提是Ubuntu主机已经配置好NFS,并且将rootfs文件放到NFS文件夹中:

setenv bootargs 'console=ttymxc0,115200 root=/dev/nfs nfsroot=192.168.1.180:/home/x-ice/workdir/nfs/rootfs,proto=tcp rw ip=192.168.1.50:192.168.1.180:192.168.1.1:255.255.255.0::eth0:off'

  注意:此处波特率前面不要有空格,否则串口终端会乱码

5.2 关于bootcmd的配置

  bootcmd 保存着 uboot 默认命令,uboot 倒计时结束以后就会执行 bootcmd 中的命令。这些命令一般都是用来启动 Linux 内核的,比如读取 EMMC 或 者 NAND Flash 中的 Linux 内核镜像文件和设备树文件到 DRAM 中,然后启动 Linux 内核。如果 EMMC 或者 NAND 中没有保存 bootcmd 的值,那么 uboot 就会使用默认的值,板子第一次运行 uboot 的时候都会使用默认值来设置 bootcmd 环境变量。

  • 我们可以通过下面这几句命令让开发板从EMMC启动
setenv bootcmd 'mmc dev 1; fatload mmc 1:1 80800000 zImage; fatload mmc 1:1 83000000 imx6ull-alientek-emmc.dtb; bootz 80800000 - 83000000'
  • 也可以通过如下命令让开发板从网络启动,前提配置好Ubuntu下的tftp功能:
setenv bootcmd 'tftp 80800000 zImage; tftp 83000000 imx6ull-alientek-emmc.dtb; bootz 80800000 - 83000000'

总结

关于 imx6ull 的 U-Boot 配置工作基本就是上述步骤,由于细节很多不能一一阐述,本文仅提供大体参考。如果大家在开发过程中遇到什么问题,欢迎在评论区留言讨论。

你可能感兴趣的:(Linux,linux)